Bug Summary

File:xlators/nfs/server/src/nfs.c
Location:line 946, column 9
Description:Access to field 'mstate' results in a dereference of a null pointer (loaded from variable 'priv')

Annotated Source Code

1/*
2 Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
3 This file is part of GlusterFS.
4
5 GlusterFS is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3 of the License,
8 or (at your option) any later version.
9
10 GlusterFS is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see
17 <http://www.gnu.org/licenses/>.
18*/
19
20/* This is the primary translator source for NFS.
21 * Every other protocol version gets initialized from here.
22 */
23
24
25#ifndef _CONFIG_H
26#define _CONFIG_H
27#include "config.h"
28#endif
29
30#include "defaults.h"
31#include "rpcsvc.h"
32#include "dict.h"
33#include "xlator.h"
34#include "nfs.h"
35#include "mem-pool.h"
36#include "logging.h"
37#include "nfs-fops.h"
38#include "inode.h"
39#include "mount3.h"
40#include "nfs3.h"
41#include "nfs-mem-types.h"
42#include "nfs3-helpers.h"
43#include "nlm4.h"
44#include "options.h"
45#include "acl3.h"
46
47#define OPT_SERVER_AUX_GIDS"nfs.server-aux-gids" "nfs.server-aux-gids"
48#define OPT_SERVER_GID_CACHE_TIMEOUT"nfs.server.aux-gid-timeout" "nfs.server.aux-gid-timeout"
49
50/* Every NFS version must call this function with the init function
51 * for its particular version.
52 */
53int
54nfs_add_initer (struct list_head *list, nfs_version_initer_t init)
55{
56 struct nfs_initer_list *new = NULL((void*)0);
57 if ((!list) || (!init))
58 return -1;
59
60 new = GF_CALLOC (1, sizeof (*new), gf_nfs_mt_nfs_initer_list)__gf_calloc (1, sizeof (*new), gf_nfs_mt_nfs_initer_list);
61 if (!new) {
62 gf_log (GF_NFS, GF_LOG_ERROR, "Memory allocation failed")do { do { if (0) printf ("Memory allocation failed"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 62, GF_LOG_ERROR
, "Memory allocation failed"); } while (0)
;
63 return -1;
64 }
65
66 new->init = init;
67 list_add_tail (&new->list, list);
68 return 0;
69}
70
71
72int
73nfs_deinit_versions (struct list_head *versions, xlator_t *this)
74{
75 struct nfs_initer_list *version = NULL((void*)0);
76 struct nfs_initer_list *tmp = NULL((void*)0);
77 struct nfs_state *nfs = NULL((void*)0);
78
79 if ((!versions) || (!this))
80 return -1;
81
82 nfs = (struct nfs_state *)this->private;
83 list_for_each_entry_safe (version, tmp, versions, list)for (version = ((typeof(*version) *)((char *)((versions)->
next)-(unsigned long)(&((typeof(*version) *)0)->list))
), tmp = ((typeof(*version) *)((char *)(version->list.next
)-(unsigned long)(&((typeof(*version) *)0)->list))); &
version->list != (versions); version = tmp, tmp = ((typeof
(*tmp) *)((char *)(tmp->list.next)-(unsigned long)(&((
typeof(*tmp) *)0)->list))))
{
84 /* TODO: Add version specific destructor.
85 * if (!version->deinit)
86 goto err;
87
88 version->deinit (this);
89 */
90 if (version->program)
91 rpcsvc_program_unregister (nfs->rpcsvc,
92 (version->program));
93
94 list_del (&version->list);
95 GF_FREE (version)__gf_free (version);
96 }
97
98 return 0;
99}
100
101int
102nfs_init_versions (struct nfs_state *nfs, xlator_t *this)
103{
104 struct nfs_initer_list *version = NULL((void*)0);
105 struct nfs_initer_list *tmp = NULL((void*)0);
106 rpcsvc_program_t *prog = NULL((void*)0);
107 int ret = -1;
108 struct list_head *versions = NULL((void*)0);
109
110 if ((!nfs) || (!this))
111 return -1;
112
113 gf_log (GF_NFS, GF_LOG_DEBUG, "Initing protocol versions")do { do { if (0) printf ("Initing protocol versions"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 113, GF_LOG_DEBUG
, "Initing protocol versions"); } while (0)
;
114 versions = &nfs->versions;
115 list_for_each_entry_safe (version, tmp, versions, list)for (version = ((typeof(*version) *)((char *)((versions)->
next)-(unsigned long)(&((typeof(*version) *)0)->list))
), tmp = ((typeof(*version) *)((char *)(version->list.next
)-(unsigned long)(&((typeof(*version) *)0)->list))); &
version->list != (versions); version = tmp, tmp = ((typeof
(*tmp) *)((char *)(tmp->list.next)-(unsigned long)(&((
typeof(*tmp) *)0)->list))))
{
116 if (!version->init) {
117 ret = -1;
118 goto err;
119 }
120
121 prog = version->init (this);
122 if (!prog) {
123 ret = -1;
124 goto err;
125 }
126// prog->actorxl = this;
127 version->program = prog;
128 if (nfs->override_portnum)
129 prog->progport = nfs->override_portnum;
130 gf_log (GF_NFS, GF_LOG_DEBUG, "Starting program: %s",do { do { if (0) printf ("Starting program: %s", prog->progname
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 131, GF_LOG_DEBUG
, "Starting program: %s", prog->progname); } while (0)
131 prog->progname)do { do { if (0) printf ("Starting program: %s", prog->progname
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 131, GF_LOG_DEBUG
, "Starting program: %s", prog->progname); } while (0)
;
132
133 ret = rpcsvc_program_register (nfs->rpcsvc, prog);
134 if (ret == -1) {
135 gf_log (GF_NFS, GF_LOG_ERROR, "Program init failed")do { do { if (0) printf ("Program init failed"); } while (0);
_gf_log ("nfs", "nfs.c", __FUNCTION__, 135, GF_LOG_ERROR, "Program init failed"
); } while (0)
;
136 goto err;
137 }
138 if (rpcsvc_register_portmap_enabled(nfs->rpcsvc)) {
139 ret = rpcsvc_program_register_portmap (prog,
140 prog->progport);
141 if (ret == -1) {
142 gf_log (GF_NFS, GF_LOG_ERROR, "Program registration failed")do { do { if (0) printf ("Program registration failed"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 142, GF_LOG_ERROR
, "Program registration failed"); } while (0)
;
143 goto err;
144 }
145 }
146 }
147
148 ret = 0;
149err:
150 return ret;
151}
152
153
154int
155nfs_add_all_initiators (struct nfs_state *nfs)
156{
157 int ret = 0;
158
159 /* Add the initializers for all versions. */
160 ret = nfs_add_initer (&nfs->versions, mnt3svc_init);
161 if (ret == -1) {
162 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 163, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
163 " initializer")do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 163, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
;
164 goto ret;
165 }
166
167 ret = nfs_add_initer (&nfs->versions, mnt1svc_init);
168 if (ret == -1) {
169 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 170, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
170 " initializer")do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 170, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
;
171 goto ret;
172 }
173
174 ret = nfs_add_initer (&nfs->versions, nfs3svc_init);
175 if (ret == -1) {
176 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 177, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
177 " initializer")do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 177, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
;
178 goto ret;
179 }
180
181 if (nfs->enable_nlm == _gf_true) {
182 ret = nfs_add_initer (&nfs->versions, nlm4svc_init);
183 if (ret == -1) {
184 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 185, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
185 " initializer")do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 185, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
;
186 goto ret;
187 }
188 }
189
190 ret = nfs_add_initer (&nfs->versions, acl3svc_init);
191 if (ret == -1) {
192 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 193, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
193 " initializer")do { do { if (0) printf ("Failed to add protocol" " initializer"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 193, GF_LOG_ERROR
, "Failed to add protocol" " initializer"); } while (0)
;
194 goto ret;
195 }
196
197 ret = 0;
198ret:
199 return ret;
200}
201
202
203int
204nfs_subvolume_started (struct nfs_state *nfs, xlator_t *xl)
205{
206 int x = 0;
207 int started = 0;
208
209 if ((!nfs) || (!xl))
210 return 1;
211
212 LOCK (&nfs->svinitlock)pthread_spin_lock (&nfs->svinitlock);
213 {
214 for (;x < nfs->allsubvols; ++x) {
215 if (nfs->initedxl[x] == xl) {
216 started = 1;
217 goto unlock;
218 }
219 }
220 }
221unlock:
222 UNLOCK (&nfs->svinitlock)pthread_spin_unlock (&nfs->svinitlock);
223
224 return started;
225}
226
227
228int
229nfs_subvolume_set_started (struct nfs_state *nfs, xlator_t *xl)
230{
231 int x = 0;
232
233 if ((!nfs) || (!xl))
234 return 1;
235
236 LOCK (&nfs->svinitlock)pthread_spin_lock (&nfs->svinitlock);
237 {
238 for (;x < nfs->allsubvols; ++x) {
239 if (nfs->initedxl[x] == xl) {
240 gf_log (GF_NFS, GF_LOG_DEBUG,do { do { if (0) printf ("Volume already started %s", xl->
name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 242
, GF_LOG_DEBUG, "Volume already started %s", xl->name); } while
(0)
241 "Volume already started %s",do { do { if (0) printf ("Volume already started %s", xl->
name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 242
, GF_LOG_DEBUG, "Volume already started %s", xl->name); } while
(0)
242 xl->name)do { do { if (0) printf ("Volume already started %s", xl->
name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 242
, GF_LOG_DEBUG, "Volume already started %s", xl->name); } while
(0)
;
243 break;
244 }
245
246 if (nfs->initedxl[x] == NULL((void*)0)) {
247 nfs->initedxl[x] = xl;
248 ++nfs->upsubvols;
249 gf_log (GF_NFS, GF_LOG_DEBUG, "Starting up: %s "do { do { if (0) printf ("Starting up: %s " ", vols started till now: %d"
, xl->name, nfs->upsubvols); } while (0); _gf_log ("nfs"
, "nfs.c", __FUNCTION__, 251, GF_LOG_DEBUG, "Starting up: %s "
", vols started till now: %d", xl->name, nfs->upsubvols
); } while (0)
250 ", vols started till now: %d", xl->name,do { do { if (0) printf ("Starting up: %s " ", vols started till now: %d"
, xl->name, nfs->upsubvols); } while (0); _gf_log ("nfs"
, "nfs.c", __FUNCTION__, 251, GF_LOG_DEBUG, "Starting up: %s "
", vols started till now: %d", xl->name, nfs->upsubvols
); } while (0)
251 nfs->upsubvols)do { do { if (0) printf ("Starting up: %s " ", vols started till now: %d"
, xl->name, nfs->upsubvols); } while (0); _gf_log ("nfs"
, "nfs.c", __FUNCTION__, 251, GF_LOG_DEBUG, "Starting up: %s "
", vols started till now: %d", xl->name, nfs->upsubvols
); } while (0)
;
252 goto unlock;
253 }
254 }
255 }
256unlock:
257 UNLOCK (&nfs->svinitlock)pthread_spin_unlock (&nfs->svinitlock);
258
259 return 0;
260}
261
262
263int32_t
264nfs_start_subvol_lookup_cbk (call_frame_t *frame, void *cookie,
265 xlator_t *this, int32_t op_ret, int32_t op_errno,
266 inode_t *inode, struct iatt *buf, dict_t *xattr,
267 struct iatt *postparent)
268{
269 if (op_ret == -1) {
270 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to lookup root: %s",do { do { if (0) printf ("Failed to lookup root: %s", strerror
(op_errno)); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 271, GF_LOG_CRITICAL, "Failed to lookup root: %s", strerror
(op_errno)); } while (0)
271 strerror (op_errno))do { do { if (0) printf ("Failed to lookup root: %s", strerror
(op_errno)); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 271, GF_LOG_CRITICAL, "Failed to lookup root: %s", strerror
(op_errno)); } while (0)
;
272 goto err;
273 }
274
275 nfs_subvolume_set_started (this->private, ((xlator_t *)cookie));
276 gf_log (GF_NFS, GF_LOG_TRACE, "Started %s", ((xlator_t *)cookie)->name)do { do { if (0) printf ("Started %s", ((xlator_t *)cookie)->
name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 276
, GF_LOG_TRACE, "Started %s", ((xlator_t *)cookie)->name);
} while (0)
;
277err:
278 return 0;
279}
280
281
282int
283nfs_startup_subvolume (xlator_t *nfsx, xlator_t *xl)
284{
285 int ret = -1;
286 loc_t rootloc = {0, };
287 nfs_user_t nfu = {0, };
288
289 if ((!nfsx) || (!xl))
290 return -1;
291
292 if (nfs_subvolume_started (nfsx->private, xl)) {
293 gf_log (GF_NFS,GF_LOG_TRACE, "Subvolume already started: %s",do { do { if (0) printf ("Subvolume already started: %s", xl->
name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 294
, GF_LOG_TRACE, "Subvolume already started: %s", xl->name)
; } while (0)
294 xl->name)do { do { if (0) printf ("Subvolume already started: %s", xl->
name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 294
, GF_LOG_TRACE, "Subvolume already started: %s", xl->name)
; } while (0)
;
295 ret = 0;
296 goto err;
297 }
298
299 ret = nfs_root_loc_fill (xl->itable, &rootloc);
300 if (ret == -1) {
301 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init root loc")do { do { if (0) printf ("Failed to init root loc"); } while (
0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 301, GF_LOG_CRITICAL
, "Failed to init root loc"); } while (0)
;
302 goto err;
303 }
304
305 nfs_user_root_create (&nfu);
306 ret = nfs_fop_lookup (nfsx, xl, &nfu, &rootloc,
307 nfs_start_subvol_lookup_cbk,
308 (void *)nfsx->private);
309 if (ret < 0) {
310 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to lookup root: %s",do { do { if (0) printf ("Failed to lookup root: %s", strerror
(-ret)); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__,
311, GF_LOG_CRITICAL, "Failed to lookup root: %s", strerror (
-ret)); } while (0)
311 strerror (-ret))do { do { if (0) printf ("Failed to lookup root: %s", strerror
(-ret)); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__,
311, GF_LOG_CRITICAL, "Failed to lookup root: %s", strerror (
-ret)); } while (0)
;
312 goto err;
313 }
314
315 nfs_loc_wipe (&rootloc);
316
317err:
318 return ret;
319}
320
321int
322nfs_startup_subvolumes (xlator_t *nfsx)
323{
324 int ret = -1;
325 xlator_list_t *cl = NULL((void*)0);
326 struct nfs_state *nfs = NULL((void*)0);
327
328 if (!nfsx)
329 return -1;
330
331 nfs = nfsx->private;
332 cl = nfs->subvols;
333 while (cl) {
334 gf_log (GF_NFS, GF_LOG_DEBUG, "Starting subvolume: %s",do { do { if (0) printf ("Starting subvolume: %s", cl->xlator
->name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 335, GF_LOG_DEBUG, "Starting subvolume: %s", cl->xlator->
name); } while (0)
335 cl->xlator->name)do { do { if (0) printf ("Starting subvolume: %s", cl->xlator
->name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 335, GF_LOG_DEBUG, "Starting subvolume: %s", cl->xlator->
name); } while (0)
;
336 ret = nfs_startup_subvolume (nfsx, cl->xlator);
337 if (ret == -1) {
338 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to start-up "do { do { if (0) printf ("Failed to start-up " "xlator: %s", cl
->xlator->name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 339, GF_LOG_CRITICAL, "Failed to start-up " "xlator: %s", cl
->xlator->name); } while (0)
339 "xlator: %s", cl->xlator->name)do { do { if (0) printf ("Failed to start-up " "xlator: %s", cl
->xlator->name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 339, GF_LOG_CRITICAL, "Failed to start-up " "xlator: %s", cl
->xlator->name); } while (0)
;
340 goto err;
341 }
342 cl = cl->next;
343 }
344
345 ret = 0;
346err:
347 return ret;
348}
349
350
351int
352nfs_init_subvolume (struct nfs_state *nfs, xlator_t *xl)
353{
354 unsigned int lrusize = 0;
355 int ret = -1;
356
357 if ((!nfs) || (!xl))
358 return -1;
359
360 lrusize = nfs->memfactor * GF_NFS_INODE_LRU_MULT6000;
361 xl->itable = inode_table_new (lrusize, xl);
362 if (!xl->itable) {
363 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to allocate "do { do { if (0) printf ("Failed to allocate " "inode table")
; } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 364, GF_LOG_CRITICAL
, "Failed to allocate " "inode table"); } while (0)
364 "inode table")do { do { if (0) printf ("Failed to allocate " "inode table")
; } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 364, GF_LOG_CRITICAL
, "Failed to allocate " "inode table"); } while (0)
;
365 goto err;
366 }
367 ret = 0;
368err:
369 return ret;
370}
371
372int
373nfs_init_subvolumes (struct nfs_state *nfs, xlator_list_t *cl)
374{
375 int ret = -1;
376 unsigned int lrusize = 0;
377 int svcount = 0;
378
379 if ((!nfs) || (!cl))
380 return -1;
381
382 lrusize = nfs->memfactor * GF_NFS_INODE_LRU_MULT6000;
383 nfs->subvols = cl;
384 gf_log (GF_NFS, GF_LOG_TRACE, "inode table lru: %d", lrusize)do { do { if (0) printf ("inode table lru: %d", lrusize); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 384, GF_LOG_TRACE
, "inode table lru: %d", lrusize); } while (0)
;
385
386 while (cl) {
387 gf_log (GF_NFS, GF_LOG_DEBUG, "Initing subvolume: %s",do { do { if (0) printf ("Initing subvolume: %s", cl->xlator
->name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 388, GF_LOG_DEBUG, "Initing subvolume: %s", cl->xlator->
name); } while (0)
388 cl->xlator->name)do { do { if (0) printf ("Initing subvolume: %s", cl->xlator
->name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 388, GF_LOG_DEBUG, "Initing subvolume: %s", cl->xlator->
name); } while (0)
;
389 ret = nfs_init_subvolume (nfs, cl->xlator);
390 if (ret == -1) {
391 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init "do { do { if (0) printf ("Failed to init " "xlator: %s", cl->
xlator->name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 392, GF_LOG_CRITICAL, "Failed to init " "xlator: %s", cl->
xlator->name); } while (0)
392 "xlator: %s", cl->xlator->name)do { do { if (0) printf ("Failed to init " "xlator: %s", cl->
xlator->name); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 392, GF_LOG_CRITICAL, "Failed to init " "xlator: %s", cl->
xlator->name); } while (0)
;
393 goto err;
394 }
395 ++svcount;
396 cl = cl->next;
397 }
398
399 LOCK_INIT (&nfs->svinitlock)pthread_spin_init (&nfs->svinitlock, 0);
400 nfs->initedxl = GF_CALLOC (svcount, sizeof (xlator_t *),__gf_calloc (svcount, sizeof (xlator_t *), gf_nfs_mt_xlator_t
)
401 gf_nfs_mt_xlator_t )__gf_calloc (svcount, sizeof (xlator_t *), gf_nfs_mt_xlator_t
)
;
402 if (!nfs->initedxl) {
403 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to allocated inited xls")do { do { if (0) printf ("Failed to allocated inited xls"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 403, GF_LOG_ERROR
, "Failed to allocated inited xls"); } while (0)
;
404 ret = -1;
405 goto err;
406 }
407
408 gf_log (GF_NFS, GF_LOG_TRACE, "Inited volumes: %d", svcount)do { do { if (0) printf ("Inited volumes: %d", svcount); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 408, GF_LOG_TRACE
, "Inited volumes: %d", svcount); } while (0)
;
409 nfs->allsubvols = svcount;
410 ret = 0;
411err:
412 return ret;
413}
414
415
416int
417nfs_user_root_create (nfs_user_t *newnfu)
418{
419 if (!newnfu)
420 return -1;
421
422 newnfu->uid = 0;
423 newnfu->gids[0] = 0;
424 newnfu->ngrps = 1;
425
426 return 0;
427}
428
429
430int
431nfs_user_create (nfs_user_t *newnfu, uid_t uid, gid_t gid, gid_t *auxgids,
432 int auxcount)
433{
434 int x = 1;
435 int y = 0;
436
437 /* We test for GF_REQUEST_MAXGROUPS instead of NFS_FOP_NGROUPS because
438 * the latter accounts for the @gid being in @auxgids, which is not the
439 * case here.
440 */
441 if ((!newnfu) || (auxcount > GF_REQUEST_MAXGROUPS16))
442 return -1;
443
444 newnfu->uid = uid;
445 newnfu->gids[0] = gid;
446 newnfu->ngrps = 1;
447
448 gf_log (GF_NFS, GF_LOG_TRACE, "uid: %d, gid %d, gids: %d", uid, gid,do { do { if (0) printf ("uid: %d, gid %d, gids: %d", uid, gid
, auxcount); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 449, GF_LOG_TRACE, "uid: %d, gid %d, gids: %d", uid, gid, auxcount
); } while (0)
449 auxcount)do { do { if (0) printf ("uid: %d, gid %d, gids: %d", uid, gid
, auxcount); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__
, 449, GF_LOG_TRACE, "uid: %d, gid %d, gids: %d", uid, gid, auxcount
); } while (0)
;
450
451 if (!auxgids)
452 return 0;
453
454 for (; y < auxcount; ++x,++y) {
455 newnfu->gids[x] = auxgids[y];
456 ++newnfu->ngrps;
457 gf_log (GF_NFS, GF_LOG_TRACE, "gid: %d", auxgids[y])do { do { if (0) printf ("gid: %d", auxgids[y]); } while (0);
_gf_log ("nfs", "nfs.c", __FUNCTION__, 457, GF_LOG_TRACE, "gid: %d"
, auxgids[y]); } while (0)
;
458 }
459
460 return 0;
461}
462
463
464void
465nfs_request_user_init (nfs_user_t *nfu, rpcsvc_request_t *req)
466{
467 gid_t *gidarr = NULL((void*)0);
468 int gids = 0;
469
470 if ((!req) || (!nfu))
471 return;
472
473 gidarr = rpcsvc_auth_unix_auxgids (req, &gids);
474 nfs_user_create (nfu, rpcsvc_request_uid (req)((req)->uid),
475 rpcsvc_request_gid (req)((req)->gid), gidarr, gids);
476
477 return;
478}
479
480void
481nfs_request_primary_user_init (nfs_user_t *nfu, rpcsvc_request_t *req,
482 uid_t uid, gid_t gid)
483{
484 gid_t *gidarr = NULL((void*)0);
485 int gids = 0;
486
487 if ((!req) || (!nfu))
488 return;
489
490 gidarr = rpcsvc_auth_unix_auxgids (req, &gids);
491 nfs_user_create (nfu, uid, gid, gidarr, gids);
492
493 return;
494}
495
496
497int32_t
498mem_acct_init (xlator_t *this)
499{
500 int ret = -1;
501
502 if (!this)
503 return ret;
504
505 ret = xlator_mem_acct_init (this, gf_nfs_mt_end + 1);
506
507 if (ret != 0) {
508 gf_log(this->name, GF_LOG_ERROR, "Memory accounting init"do { do { if (0) printf ("Memory accounting init" "failed"); }
while (0); _gf_log (this->name, "nfs.c", __FUNCTION__, 509
, GF_LOG_ERROR, "Memory accounting init" "failed"); } while (
0)
509 "failed")do { do { if (0) printf ("Memory accounting init" "failed"); }
while (0); _gf_log (this->name, "nfs.c", __FUNCTION__, 509
, GF_LOG_ERROR, "Memory accounting init" "failed"); } while (
0)
;
510 return ret;
511 }
512
513 return ret;
514}
515
516
517struct nfs_state *
518nfs_init_state (xlator_t *this)
519{
520 struct nfs_state *nfs = NULL((void*)0);
521 int ret = -1;
522 unsigned int fopspoolsize = 0;
523 char *optstr = NULL((void*)0);
524 gf_boolean_t boolt = _gf_false;
525 struct stat stbuf = {0,};
526
527 if (!this)
528 return NULL((void*)0);
529
530 if ((!this->children) || (!this->children->xlator)) {
531 gf_log (GF_NFS, GF_LOG_ERROR, "nfs must have at least one"do { do { if (0) printf ("nfs must have at least one" " child subvolume"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 532, GF_LOG_ERROR
, "nfs must have at least one" " child subvolume"); } while (
0)
532 " child subvolume")do { do { if (0) printf ("nfs must have at least one" " child subvolume"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 532, GF_LOG_ERROR
, "nfs must have at least one" " child subvolume"); } while (
0)
;
533 return NULL((void*)0);
534 }
535
536 nfs = GF_CALLOC (1, sizeof (*nfs), gf_nfs_mt_nfs_state)__gf_calloc (1, sizeof (*nfs), gf_nfs_mt_nfs_state);
537 if (!nfs) {
538 gf_log (GF_NFS, GF_LOG_ERROR, "memory allocation failed")do { do { if (0) printf ("memory allocation failed"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 538, GF_LOG_ERROR
, "memory allocation failed"); } while (0)
;
539 return NULL((void*)0);
540 }
541
542 nfs->memfactor = GF_NFS_DEFAULT_MEMFACTOR15;
543 if (dict_get (this->options, "nfs.mem-factor")) {
544 ret = dict_get_str (this->options, "nfs.mem-factor",
545 &optstr);
546 if (ret < 0) {
547 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict")do { do { if (0) printf ("Failed to parse dict"); } while (0)
; _gf_log ("nfs", "nfs.c", __FUNCTION__, 547, GF_LOG_ERROR, "Failed to parse dict"
); } while (0)
;
548 goto free_rpcsvc;
549 }
550
551 ret = gf_string2uint (optstr, &nfs->memfactor);
552 if (ret < 0) {
553 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse uint "do { do { if (0) printf ("Failed to parse uint " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 554, GF_LOG_ERROR
, "Failed to parse uint " "string"); } while (0)
554 "string")do { do { if (0) printf ("Failed to parse uint " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 554, GF_LOG_ERROR
, "Failed to parse uint " "string"); } while (0)
;
555 goto free_rpcsvc;
556 }
557 }
558
559 fopspoolsize = nfs->memfactor * GF_NFS_CONCURRENT_OPS_MULT15;
560 /* FIXME: Really saddens me to see this as xlator wide. */
561 nfs->foppool = mem_pool_new (struct nfs_fop_local, fopspoolsize)mem_pool_new_fn (sizeof(struct nfs_fop_local), fopspoolsize, "struct nfs_fop_local"
)
;
562 if (!nfs->foppool) {
563 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to allocate fops "do { do { if (0) printf ("Failed to allocate fops " "local pool"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 564, GF_LOG_CRITICAL
, "Failed to allocate fops " "local pool"); } while (0)
564 "local pool")do { do { if (0) printf ("Failed to allocate fops " "local pool"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 564, GF_LOG_CRITICAL
, "Failed to allocate fops " "local pool"); } while (0)
;
565 goto free_rpcsvc;
566 }
567
568 nfs->dynamicvolumes = GF_NFS_DVM_OFF2;
569 if (dict_get (this->options, "nfs.dynamic-volumes")) {
570 ret = dict_get_str (this->options, "nfs.dynamic-volumes",
571 &optstr);
572 if (ret < 0) {
573 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict")do { do { if (0) printf ("Failed to parse dict"); } while (0)
; _gf_log ("nfs", "nfs.c", __FUNCTION__, 573, GF_LOG_ERROR, "Failed to parse dict"
); } while (0)
;
574 goto free_foppool;
575 }
576
577 ret = gf_string2boolean (optstr, &boolt);
578 if (ret < 0) {
579 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 580, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
580 "string")do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 580, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
;
581 goto free_foppool;
582 }
583
584 if (boolt == _gf_true)
585 nfs->dynamicvolumes = GF_NFS_DVM_ON1;
586 }
587
588 nfs->enable_nlm = _gf_true;
589 if (!dict_get_str (this->options, "nfs.nlm", &optstr)) {
590
591 ret = gf_string2boolean (optstr, &boolt);
592 if (ret < 0) {
593 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse"do { do { if (0) printf ("Failed to parse" " bool string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 594, GF_LOG_ERROR
, "Failed to parse" " bool string"); } while (0)
594 " bool string")do { do { if (0) printf ("Failed to parse" " bool string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 594, GF_LOG_ERROR
, "Failed to parse" " bool string"); } while (0)
;
595 goto free_foppool;
596 }
597
598 if (boolt == _gf_false) {
599 gf_log (GF_NFS, GF_LOG_INFO, "NLM is manually disabled")do { do { if (0) printf ("NLM is manually disabled"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 599, GF_LOG_INFO
, "NLM is manually disabled"); } while (0)
;
600 nfs->enable_nlm = _gf_false;
601 }
602 }
603
604 nfs->enable_ino32 = 0;
605 if (dict_get (this->options, "nfs.enable-ino32")) {
606 ret = dict_get_str (this->options, "nfs.enable-ino32",
607 &optstr);
608 if (ret < 0) {
609 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict")do { do { if (0) printf ("Failed to parse dict"); } while (0)
; _gf_log ("nfs", "nfs.c", __FUNCTION__, 609, GF_LOG_ERROR, "Failed to parse dict"
); } while (0)
;
610 goto free_foppool;
611 }
612
613 ret = gf_string2boolean (optstr, &boolt);
614 if (ret < 0) {
615 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 616, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
616 "string")do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 616, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
;
617 goto free_foppool;
618 }
619
620 if (boolt == _gf_true)
621 nfs->enable_ino32 = 1;
622 }
623
624 if (dict_get (this->options, "nfs.port")) {
625 ret = dict_get_str (this->options, "nfs.port",
626 &optstr);
627 if (ret < 0) {
628 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict")do { do { if (0) printf ("Failed to parse dict"); } while (0)
; _gf_log ("nfs", "nfs.c", __FUNCTION__, 628, GF_LOG_ERROR, "Failed to parse dict"
); } while (0)
;
629 goto free_foppool;
630 }
631
632 ret = gf_string2uint (optstr, &nfs->override_portnum);
633 if (ret < 0) {
634 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse uint "do { do { if (0) printf ("Failed to parse uint " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 635, GF_LOG_ERROR
, "Failed to parse uint " "string"); } while (0)
635 "string")do { do { if (0) printf ("Failed to parse uint " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 635, GF_LOG_ERROR
, "Failed to parse uint " "string"); } while (0)
;
636 goto free_foppool;
637 }
638 }
639
640 if (dict_get(this->options, "transport.socket.listen-port") == NULL((void*)0)) {
641 if (nfs->override_portnum)
642 ret = gf_asprintf (&optstr, "%d",
643 nfs->override_portnum);
644 else
645 ret = gf_asprintf (&optstr, "%d", GF_NFS3_PORT2049);
646 if (ret == -1) {
647 gf_log (GF_NFS, GF_LOG_ERROR, "failed mem-allocation")do { do { if (0) printf ("failed mem-allocation"); } while (0
); _gf_log ("nfs", "nfs.c", __FUNCTION__, 647, GF_LOG_ERROR, "failed mem-allocation"
); } while (0)
;
648 goto free_foppool;
649 }
650 ret = dict_set_dynstr (this->options,
651 "transport.socket.listen-port", optstr);
652 if (ret == -1) {
653 gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_dynstr error")do { do { if (0) printf ("dict_set_dynstr error"); } while (0
); _gf_log ("nfs", "nfs.c", __FUNCTION__, 653, GF_LOG_ERROR, "dict_set_dynstr error"
); } while (0)
;
654 goto free_foppool;
655 }
656 }
657
658 if (dict_get(this->options, "transport-type") == NULL((void*)0)) {
659 ret = dict_set_str (this->options, "transport-type", "socket");
660 if (ret == -1) {
661 gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error")do { do { if (0) printf ("dict_set_str error"); } while (0); _gf_log
("nfs", "nfs.c", __FUNCTION__, 661, GF_LOG_ERROR, "dict_set_str error"
); } while (0)
;
662 goto free_foppool;
663 }
664 }
665
666 nfs->mount_udp = 0;
667 if (dict_get(this->options, "nfs.mount-udp")) {
668 ret = dict_get_str (this->options, "nfs.mount-udp", &optstr);
669 if (ret == -1) {
670 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict")do { do { if (0) printf ("Failed to parse dict"); } while (0)
; _gf_log ("nfs", "nfs.c", __FUNCTION__, 670, GF_LOG_ERROR, "Failed to parse dict"
); } while (0)
;
671 goto free_foppool;
672 }
673
674 ret = gf_string2boolean (optstr, &boolt);
675 if (ret < 0) {
676 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 677, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
677 "string")do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 677, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
;
678 goto free_foppool;
679 }
680
681 if (boolt == _gf_true)
682 nfs->mount_udp = 1;
683 }
684
685 /* support both options rpc-auth.ports.insecure and
686 * rpc-auth-allow-insecure for backward compatibility
687 */
688 nfs->allow_insecure = 1;
689 if (dict_get(this->options, "rpc-auth.ports.insecure")) {
690 ret = dict_get_str (this->options, "rpc-auth.ports.insecure",
691 &optstr);
692 if (ret < 0) {
693 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict")do { do { if (0) printf ("Failed to parse dict"); } while (0)
; _gf_log ("nfs", "nfs.c", __FUNCTION__, 693, GF_LOG_ERROR, "Failed to parse dict"
); } while (0)
;
694 goto free_foppool;
695 }
696
697 ret = gf_string2boolean (optstr, &boolt);
698 if (ret < 0) {
699 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 700, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
700 "string")do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 700, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
;
701 goto free_foppool;
702 }
703
704 if (boolt == _gf_false)
705 nfs->allow_insecure = 0;
706 }
707
708 if (dict_get(this->options, "rpc-auth-allow-insecure")) {
709 ret = dict_get_str (this->options, "rpc-auth-allow-insecure",
710 &optstr);
711 if (ret < 0) {
712 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict")do { do { if (0) printf ("Failed to parse dict"); } while (0)
; _gf_log ("nfs", "nfs.c", __FUNCTION__, 712, GF_LOG_ERROR, "Failed to parse dict"
); } while (0)
;
713 goto free_foppool;
714 }
715
716 ret = gf_string2boolean (optstr, &boolt);
717 if (ret < 0) {
718 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 719, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
719 "string")do { do { if (0) printf ("Failed to parse bool " "string"); }
while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 719, GF_LOG_ERROR
, "Failed to parse bool " "string"); } while (0)
;
720 goto free_foppool;
721 }
722
723 if (boolt == _gf_false)
724 nfs->allow_insecure = 0;
725 }
726
727 if (nfs->allow_insecure) {
728 /* blindly set both the options */
729 dict_del (this->options, "rpc-auth-allow-insecure");
730 ret = dict_set_str (this->options,
731 "rpc-auth-allow-insecure", "on");
732 if (ret == -1) {
733 gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error")do { do { if (0) printf ("dict_set_str error"); } while (0); _gf_log
("nfs", "nfs.c", __FUNCTION__, 733, GF_LOG_ERROR, "dict_set_str error"
); } while (0)
;
734 goto free_foppool;
735 }
736 dict_del (this->options, "rpc-auth.ports.insecure");
737 ret = dict_set_str (this->options,
738 "rpc-auth.ports.insecure", "on");
739 if (ret == -1) {
740 gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error")do { do { if (0) printf ("dict_set_str error"); } while (0); _gf_log
("nfs", "nfs.c", __FUNCTION__, 740, GF_LOG_ERROR, "dict_set_str error"
); } while (0)
;
741 goto free_foppool;
742 }
743 }
744
745 GF_OPTION_INIT (OPT_SERVER_AUX_GIDS, nfs->server_aux_gids,do { int val_ret = 0; val_ret = xlator_option_init_bool ((*__glusterfs_this_location
()), (*__glusterfs_this_location())->options, "nfs.server-aux-gids"
, &(nfs->server_aux_gids)); if (val_ret) goto free_foppool
; } while (0)
746 bool, free_foppool)do { int val_ret = 0; val_ret = xlator_option_init_bool ((*__glusterfs_this_location
()), (*__glusterfs_this_location())->options, "nfs.server-aux-gids"
, &(nfs->server_aux_gids)); if (val_ret) goto free_foppool
; } while (0)
;
747 GF_OPTION_INIT (OPT_SERVER_GID_CACHE_TIMEOUT, nfs->server_aux_gids_max_age,do { int val_ret = 0; val_ret = xlator_option_init_uint32 ((*
__glusterfs_this_location()), (*__glusterfs_this_location())->
options, "nfs.server.aux-gid-timeout", &(nfs->server_aux_gids_max_age
)); if (val_ret) goto free_foppool; } while (0)
748 uint32, free_foppool)do { int val_ret = 0; val_ret = xlator_option_init_uint32 ((*
__glusterfs_this_location()), (*__glusterfs_this_location())->
options, "nfs.server.aux-gid-timeout", &(nfs->server_aux_gids_max_age
)); if (val_ret) goto free_foppool; } while (0)
;
749
750 if (gid_cache_init(&nfs->gid_cache, nfs->server_aux_gids_max_age) < 0) {
751 gf_log(GF_NFS, GF_LOG_ERROR, "Failed to initialize group cache.")do { do { if (0) printf ("Failed to initialize group cache.")
; } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 751, GF_LOG_ERROR
, "Failed to initialize group cache."); } while (0)
;
752 goto free_foppool;
753 }
754
755 if (stat("/sbin/rpc.statd", &stbuf) == -1) {
756 gf_log (GF_NFS, GF_LOG_WARNING, "/sbin/rpc.statd not found. "do { do { if (0) printf ("/sbin/rpc.statd not found. " "Disabling NLM"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 757, GF_LOG_WARNING
, "/sbin/rpc.statd not found. " "Disabling NLM"); } while (0)
757 "Disabling NLM")do { do { if (0) printf ("/sbin/rpc.statd not found. " "Disabling NLM"
); } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 757, GF_LOG_WARNING
, "/sbin/rpc.statd not found. " "Disabling NLM"); } while (0)
;
758 nfs->enable_nlm = _gf_false;
759 }
760
761 nfs->rpcsvc = rpcsvc_init (this, this->ctx, this->options, 0);
762 if (!nfs->rpcsvc) {
763 ret = -1;
764 gf_log (GF_NFS, GF_LOG_ERROR, "RPC service init failed")do { do { if (0) printf ("RPC service init failed"); } while (
0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 764, GF_LOG_ERROR,
"RPC service init failed"); } while (0)
;
765 goto free_foppool;
766 }
767
768 this->private = (void *)nfs;
769 INIT_LIST_HEAD (&nfs->versions)do { (&nfs->versions)->next = (&nfs->versions
)->prev = &nfs->versions; } while (0)
;
770 nfs->generation = 1965;
771
772 ret = 0;
773
774free_foppool:
775 if (ret < 0)
776 mem_pool_destroy (nfs->foppool);
777
778free_rpcsvc:
779 /*
780 * rpcsvc_deinit */
781 if (ret < 0) {
782 GF_FREE (nfs)__gf_free (nfs);
783 nfs = NULL((void*)0);
784 }
785
786 return nfs;
787}
788
789
790int
791init (xlator_t *this) {
792
793 struct nfs_state *nfs = NULL((void*)0);
794 int ret = -1;
795
796 if (!this)
797 return -1;
798
799 nfs = nfs_init_state (this);
800 if (!nfs) {
801 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to init nfs option")do { do { if (0) printf ("Failed to init nfs option"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 801, GF_LOG_ERROR
, "Failed to init nfs option"); } while (0)
;
802 return -1;
803 }
804
805 ret = nfs_add_all_initiators (nfs);
806 if (ret == -1) {
807 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add initiators")do { do { if (0) printf ("Failed to add initiators"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 807, GF_LOG_ERROR
, "Failed to add initiators"); } while (0)
;
808 goto err;
809 }
810
811 ret = nfs_init_subvolumes (nfs, this->children);
812 if (ret == -1) {
813 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NFS "do { do { if (0) printf ("Failed to init NFS " "exports"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 814, GF_LOG_CRITICAL
, "Failed to init NFS " "exports"); } while (0)
814 "exports")do { do { if (0) printf ("Failed to init NFS " "exports"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 814, GF_LOG_CRITICAL
, "Failed to init NFS " "exports"); } while (0)
;
815 goto err;
816 }
817
818 ret = mount_init_state (this);
819 if (ret == -1) {
820 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init Mount"do { do { if (0) printf ("Failed to init Mount" "state"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 821, GF_LOG_CRITICAL
, "Failed to init Mount" "state"); } while (0)
821 "state")do { do { if (0) printf ("Failed to init Mount" "state"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 821, GF_LOG_CRITICAL
, "Failed to init Mount" "state"); } while (0)
;
822 goto err;
823 }
824
825 ret = nlm4_init_state (this);
826 if (ret == -1) {
827 gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NLM"do { do { if (0) printf ("Failed to init NLM" "state"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 828, GF_LOG_CRITICAL
, "Failed to init NLM" "state"); } while (0)
828 "state")do { do { if (0) printf ("Failed to init NLM" "state"); } while
(0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 828, GF_LOG_CRITICAL
, "Failed to init NLM" "state"); } while (0)
;
829 goto err;
830 }
831
832 ret = nfs_init_versions (nfs, this);
833 if (ret == -1) {
834 gf_log (GF_NFS, GF_LOG_ERROR, "Failed to initialize "do { do { if (0) printf ("Failed to initialize " "protocols")
; } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 835, GF_LOG_ERROR
, "Failed to initialize " "protocols"); } while (0)
835 "protocols")do { do { if (0) printf ("Failed to initialize " "protocols")
; } while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 835, GF_LOG_ERROR
, "Failed to initialize " "protocols"); } while (0)
;
836 /* Do not return an error on this. If we dont return
837 * an error, the process keeps running and it helps
838 * to point out where the log is by doing ps ax|grep gluster.
839 */
840 ret = 0;
841 goto err;
842 }
843
844 gf_log (GF_NFS, GF_LOG_INFO, "NFS service started")do { do { if (0) printf ("NFS service started"); } while (0);
_gf_log ("nfs", "nfs.c", __FUNCTION__, 844, GF_LOG_INFO, "NFS service started"
); } while (0)
;
845err:
846
847 return ret;
848}
849
850
851int
852notify (xlator_t *this, int32_t event, void *data, ...)
853{
854 xlator_t *subvol = NULL((void*)0);
855 struct nfs_state *priv = NULL((void*)0);
856
857 subvol = (xlator_t *)data;
858
859 gf_log (GF_NFS, GF_LOG_TRACE, "Notification received: %d",do { do { if (0) printf ("Notification received: %d", event);
} while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 860, GF_LOG_TRACE
, "Notification received: %d", event); } while (0)
860 event)do { do { if (0) printf ("Notification received: %d", event);
} while (0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 860, GF_LOG_TRACE
, "Notification received: %d", event); } while (0)
;
861
862 switch (event) {
863 case GF_EVENT_CHILD_UP:
864 nfs_startup_subvolume (this, subvol);
865 break;
866
867 case GF_EVENT_CHILD_MODIFIED:
868 priv = this->private;
869 ++(priv->generation);
870 break;
871
872 case GF_EVENT_PARENT_UP:
873 default_notify (this, GF_EVENT_PARENT_UP, data);
874 break;
875 }
876
877 return 0;
878}
879
880
881int
882fini (xlator_t *this)
883{
884
885 struct nfs_state *nfs = NULL((void*)0);
886
887 nfs = (struct nfs_state *)this->private;
888 gf_log (GF_NFS, GF_LOG_DEBUG, "NFS service going down")do { do { if (0) printf ("NFS service going down"); } while (
0); _gf_log ("nfs", "nfs.c", __FUNCTION__, 888, GF_LOG_DEBUG,
"NFS service going down"); } while (0)
;
889 nfs_deinit_versions (&nfs->versions, this);
890 return 0;
891}
892
893int32_t
894nfs_forget (xlator_t *this, inode_t *inode)
895{
896 uint64_t ctx = 0;
897 struct nfs_inode_ctx *ictx = NULL((void*)0);
898
899 if (inode_ctx_del (inode, this, &ctx)inode_ctx_del2(inode,this,&ctx,0))
900 return -1;
901
902 ictx = (struct nfs_inode_ctx *)ctx;
903 GF_FREE (ictx)__gf_free (ictx);
904
905 return 0;
906}
907
908gf_boolean_t
909_nfs_export_is_for_vol (char *exname, char *volname)
910{
911 gf_boolean_t ret = _gf_false;
912 char *tmp = NULL((void*)0);
913
914 tmp = exname;
915 if (tmp[0] == '/')
916 tmp++;
917
918 if (!strcmp (tmp, volname))
919 ret = _gf_true;
920
921 return ret;
922}
923
924int
925nfs_priv_to_dict (xlator_t *this, dict_t *dict)
926{
927 int ret = -1;
928 struct nfs_state *priv = NULL((void*)0);
929 struct mountentry *mentry = NULL((void*)0);
930 char *volname = NULL((void*)0);
931 char key[1024] = {0,};
932 int count = 0;
933
934 GF_VALIDATE_OR_GOTO (THIS->name, this, out)do { if (!this) { (*__errno_location ()) = 22; do { do { if (
0) printf ("invalid argument: " "this"); } while (0); _gf_log_callingfn
((*__glusterfs_this_location())->name, "nfs.c", __FUNCTION__
, 934, GF_LOG_ERROR, "invalid argument: " "this"); } while (0
); goto out; } } while (0)
;
935 GF_VALIDATE_OR_GOTO (THIS->name, dict, out)do { if (!dict) { (*__errno_location ()) = 22; do { do { if (
0) printf ("invalid argument: " "dict"); } while (0); _gf_log_callingfn
((*__glusterfs_this_location())->name, "nfs.c", __FUNCTION__
, 935, GF_LOG_ERROR, "invalid argument: " "dict"); } while (0
); goto out; } } while (0)
;
936
937 priv = this->private;
1
Value assigned to 'priv'
938 GF_ASSERT (priv)do { if (!(priv)) { do { do { if (0) printf ("Assertion failed: "
"priv"); } while (0); _gf_log_callingfn ("", "nfs.c", __FUNCTION__
, 938, GF_LOG_ERROR, "Assertion failed: " "priv"); } while (0
); } } while (0)
;
2
Within the expansion of the macro 'GF_ASSERT':
a
Assuming 'priv' is null
939
940 ret = dict_get_str (dict, "volname", &volname);
941 if (ret) {
3
Assuming 'ret' is 0
4
Taking false branch
942 gf_log (this->name, GF_LOG_ERROR, "Could not get volname")do { do { if (0) printf ("Could not get volname"); } while (0
); _gf_log (this->name, "nfs.c", __FUNCTION__, 942, GF_LOG_ERROR
, "Could not get volname"); } while (0)
;
943 goto out;
944 }
945
946 list_for_each_entry (mentry, &priv->mstate->mountlist, mlist)for (mentry = ((typeof(*mentry) *)((char *)((&priv->mstate
->mountlist)->next)-(unsigned long)(&((typeof(*mentry
) *)0)->mlist))); &mentry->mlist != (&priv->
mstate->mountlist); mentry = ((typeof(*mentry) *)((char *)
(mentry->mlist.next)-(unsigned long)(&((typeof(*mentry
) *)0)->mlist))))
{
5
Within the expansion of the macro 'list_for_each_entry':
a
Access to field 'mstate' results in a dereference of a null pointer (loaded from variable 'priv')
947 if (!_nfs_export_is_for_vol (mentry->exname, volname))
948 continue;
949
950 memset (key, 0, sizeof (key));
951 snprintf (key, sizeof (key), "client%d.hostname", count);
952 ret = dict_set_str (dict, key, mentry->hostname);
953 if (ret) {
954 gf_log (this->name, GF_LOG_ERROR,do { do { if (0) printf ("Error writing hostname to dict"); }
while (0); _gf_log (this->name, "nfs.c", __FUNCTION__, 955
, GF_LOG_ERROR, "Error writing hostname to dict"); } while (0
)
955 "Error writing hostname to dict")do { do { if (0) printf ("Error writing hostname to dict"); }
while (0); _gf_log (this->name, "nfs.c", __FUNCTION__, 955
, GF_LOG_ERROR, "Error writing hostname to dict"); } while (0
)
;
956 goto out;
957 }
958
959 /* No connection data available yet in nfs server.
960 * Hence, setting to 0 to prevent cli failing
961 */
962 memset (key, 0, sizeof (key));
963 snprintf (key, sizeof (key), "client%d.bytesread", count);
964 ret = dict_set_uint64 (dict, key, 0);
965 if (ret) {
966 gf_log (this->name, GF_LOG_ERROR,do { do { if (0) printf ("Error writing bytes read to dict");
} while (0); _gf_log (this->name, "nfs.c", __FUNCTION__, 967
, GF_LOG_ERROR, "Error writing bytes read to dict"); } while (
0)
967 "Error writing bytes read to dict")do { do { if (0) printf ("Error writing bytes read to dict");
} while (0); _gf_log (this->name, "nfs.c", __FUNCTION__, 967
, GF_LOG_ERROR, "Error writing bytes read to dict"); } while (
0)
;
968 goto out;
969 }
970
971 memset (key, 0, sizeof (key));
972 snprintf (key, sizeof (key), "client%d.byteswrite", count);
973 ret = dict_set_uint64 (dict, key, 0);
974 if (ret) {
975 gf_log (this->name, GF_LOG_ERROR,do { do { if (0) printf ("Error writing bytes write to dict")
; } while (0); _gf_log (this->name, "nfs.c", __FUNCTION__,
976, GF_LOG_ERROR, "Error writing bytes write to dict"); } while
(0)
976 "Error writing bytes write to dict")do { do { if (0) printf ("Error writing bytes write to dict")
; } while (0); _gf_log (this->name, "nfs.c", __FUNCTION__,
976, GF_LOG_ERROR, "Error writing bytes write to dict"); } while
(0)
;
977 goto out;
978 }
979
980 count++;
981 }
982
983 ret = dict_set_int32 (dict, "clientcount", count);
984 if (ret)
985 gf_log (this->name, GF_LOG_ERROR,do { do { if (0) printf ("Error writing client count to dict"
); } while (0); _gf_log (this->name, "nfs.c", __FUNCTION__
, 986, GF_LOG_ERROR, "Error writing client count to dict"); }
while (0)
986 "Error writing client count to dict")do { do { if (0) printf ("Error writing client count to dict"
); } while (0); _gf_log (this->name, "nfs.c", __FUNCTION__
, 986, GF_LOG_ERROR, "Error writing client count to dict"); }
while (0)
;
987
988out:
989 gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret)do { do { if (0) printf ("Returning %d", ret); } while (0); _gf_log
((*__glusterfs_this_location())->name, "nfs.c", __FUNCTION__
, 989, GF_LOG_DEBUG, "Returning %d", ret); } while (0)
;
990 return ret;
991}
992
993extern int32_t
994nlm_priv (xlator_t *this);
995
996int32_t
997nfs_priv (xlator_t *this)
998{
999 return nlm_priv (this);
1000}
1001
1002
1003struct xlator_cbks cbks = {
1004 .forget = nfs_forget,
1005};
1006
1007struct xlator_fops fops;
1008
1009struct xlator_dumpops dumpops = {
1010 .priv = nfs_priv,
1011 .priv_to_dict = nfs_priv_to_dict,
1012};
1013
1014/* TODO: If needed, per-volume options below can be extended to be export
1015+ * specific also because after export-dir is introduced, a volume is not
1016+ * neccessarily an export whereas different subdirectories within that volume
1017+ * can be and may need these options to be specified separately.
1018+ */
1019struct volume_options options[] = {
1020 { .key = {"nfs3.read-size"},
1021 .type = GF_OPTION_TYPE_SIZET,
1022 .description = "Size in which the client should issue read requests"
1023 " to the Gluster NFSv3 server. Must be a multiple of"
1024 " 4KB."
1025 },
1026 { .key = {"nfs3.write-size"},
1027 .type = GF_OPTION_TYPE_SIZET,
1028 .description = "Size in which the client should issue write requests"
1029 " to the Gluster NFSv3 server. Must be a multiple of"
1030 " 4KB."
1031 },
1032 { .key = {"nfs3.readdir-size"},
1033 .type = GF_OPTION_TYPE_SIZET,
1034 .description = "Size in which the client should issue directory "
1035 " reading requests."
1036 },
1037 { .key = {"nfs3.*.volume-access"},
1038 .type = GF_OPTION_TYPE_STR,
1039 .value = {"read-only", "read-write"},
1040 .description = "Type of access desired for this subvolume: "
1041 " read-only, read-write(default)"
1042 },
1043 { .key = {"nfs3.*.trusted-write"},
1044 .type = GF_OPTION_TYPE_BOOL,
1045 .description = "On an UNSTABLE write from client, return STABLE flag"
1046 " to force client to not send a COMMIT request. In "
1047 "some environments, combined with a replicated "
1048 "GlusterFS setup, this option can improve write "
1049 "performance. This flag allows user to trust Gluster"
1050 " replication logic to sync data to the disks and "
1051 "recover when required. COMMIT requests if received "
1052 "will be handled in a default manner by fsyncing."
1053 " STABLE writes are still handled in a sync manner. "
1054 "Off by default."
1055
1056 },
1057 { .key = {"nfs3.*.trusted-sync"},
1058 .type = GF_OPTION_TYPE_BOOL,
1059 .description = "All writes and COMMIT requests are treated as async."
1060 " This implies that no write requests are guaranteed"
1061 " to be on server disks when the write reply is "
1062 "received at the NFS client. Trusted sync includes "
1063 " trusted-write behaviour. Off by default."
1064
1065 },
1066 { .key = {"nfs3.*.export-dir"},
1067 .type = GF_OPTION_TYPE_PATH,
1068 .description = "By default, all subvolumes of nfs are exported as "
1069 "individual exports. There are cases where a "
1070 "subdirectory or subdirectories in the volume need to "
1071 "be exported separately. This option can also be used "
1072 "in conjunction with nfs3.export-volumes option to "
1073 "restrict exports only to the subdirectories specified"
1074 " through this option. Must be an absolute path."
1075 },
1076 { .key = {"nfs3.export-dirs"},
1077 .type = GF_OPTION_TYPE_BOOL,
1078 .description = "By default, all subvolumes of nfs are exported as "
1079 "individual exports. There are cases where a "
1080 "subdirectory or subdirectories in the volume need to "
1081 "be exported separately. Enabling this option allows "
1082 "any directory on a volumes to be exported separately."
1083 " Directory exports are enabled by default."
1084 },
1085 { .key = {"nfs3.export-volumes"},
1086 .type = GF_OPTION_TYPE_BOOL,
1087 .description = "Enable or disable exporting whole volumes, instead "
1088 "if used in conjunction with nfs3.export-dir, can "
1089 "allow setting up only subdirectories as exports. On "
1090 "by default."
1091 },
1092 { .key = {"rpc-auth.auth-unix"},
1093 .type = GF_OPTION_TYPE_BOOL,
1094 .description = "Disable or enable the AUTH_UNIX authentication type."
1095 "Must always be enabled for better interoperability."
1096 "However, can be disabled if needed. Enabled by"
1097 "default"
1098 },
1099 { .key = {"rpc-auth.auth-null"},
1100 .type = GF_OPTION_TYPE_BOOL,
1101 .description = "Disable or enable the AUTH_NULL authentication type."
1102 "Must always be enabled. This option is here only to"
1103 " avoid unrecognized option warnings"
1104 },
1105 { .key = {"rpc-auth.auth-unix.*"},
1106 .type = GF_OPTION_TYPE_BOOL,
1107 .description = "Disable or enable the AUTH_UNIX authentication type "
1108 "for a particular exported volume overriding defaults"
1109 " and general setting for AUTH_UNIX scheme. Must "
1110 "always be enabled for better interoperability."
1111 "However, can be disabled if needed. Enabled by"
1112 "default."
1113 },
1114 { .key = {"rpc-auth.auth-unix.*.allow"},
1115 .type = GF_OPTION_TYPE_STR,
1116 .description = "Disable or enable the AUTH_UNIX authentication type "
1117 "for a particular exported volume overriding defaults"
1118 " and general setting for AUTH_UNIX scheme. Must "
1119 "always be enabled for better interoperability."
1120 "However, can be disabled if needed. Enabled by"
1121 "default."
1122 },
1123 { .key = {"rpc-auth.auth-null.*"},
1124 .type = GF_OPTION_TYPE_BOOL,
1125 .description = "Disable or enable the AUTH_NULL authentication type "
1126 "for a particular exported volume overriding defaults"
1127 " and general setting for AUTH_NULL. Must always be "
1128 "enabled. This option is here only to avoid "
1129 "unrecognized option warnings."
1130 },
1131 { .key = {"rpc-auth.addr.allow"},
1132 .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
1133 .description = "Allow a comma separated list of addresses and/or"
1134 " hostnames to connect to the server. By default, all"
1135 " connections are allowed. This allows users to "
1136 "define a general rule for all exported volumes."
1137 },
1138 { .key = {"rpc-auth.addr.reject"},
1139 .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
1140 .description = "Reject a comma separated list of addresses and/or"
1141 " hostnames from connecting to the server. By default,"
1142 " all connections are allowed. This allows users to"
1143 "define a general rule for all exported volumes."
1144 },
1145 { .key = {"rpc-auth.addr.*.allow"},
1146 .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
1147 .description = "Allow a comma separated list of addresses and/or"
1148 " hostnames to connect to the server. By default, all"
1149 " connections are allowed. This allows users to "
1150 "define a rule for a specific exported volume."
1151 },
1152 { .key = {"rpc-auth.addr.*.reject"},
1153 .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
1154 .description = "Reject a comma separated list of addresses and/or"
1155 " hostnames from connecting to the server. By default,"
1156 " all connections are allowed. This allows users to"
1157 "define a rule for a specific exported volume."
1158 },
1159 { .key = {"rpc-auth.ports.insecure"},
1160 .type = GF_OPTION_TYPE_BOOL,
1161 .description = "Allow client connections from unprivileged ports. By "
1162 "default only privileged ports are allowed. This is a"
1163 "global setting in case insecure ports are to be "
1164 "enabled for all exports using a single option."
1165 },
1166 { .key = {"rpc-auth.ports.*.insecure"},
1167 .type = GF_OPTION_TYPE_BOOL,
1168 .description = "Allow client connections from unprivileged ports. By "
1169 "default only privileged ports are allowed. Use this"
1170 " option to enable or disable insecure ports for "
1171 "a specific subvolume and to override the global setting "
1172 " set by the previous option."
1173 },
1174 { .key = {"rpc-auth.addr.namelookup"},
1175 .type = GF_OPTION_TYPE_BOOL,
1176 .description = "Users have the option of turning on name lookup for"
1177 " incoming client connections using this option. Use this "
1178 "option to turn on name lookups during address-based "
1179 "authentication. Turning this on will enable you to"
1180 " use hostnames in rpc-auth.addr.* filters. In some "
1181 "setups, the name server can take too long to reply to DNS "
1182 "queries resulting in timeouts of mount requests. By default, "
1183 " name lookup is off"
1184 },
1185 { .key = {"nfs.dynamic-volumes"},
1186 .type = GF_OPTION_TYPE_BOOL,
1187 .description = "Internal option set to tell gnfs to use a different"
1188 " scheme for encoding file handles when DVM is being"
1189 " used."
1190 },
1191 { .key = {"nfs3.*.volume-id"},
1192 .type = GF_OPTION_TYPE_STR,
1193 .description = "When nfs.dynamic-volumes is set, gnfs expects every "
1194 "subvolume to have this option set for it, so that "
1195 "gnfs can use this option to identify the volume. "
1196 "If all subvolumes do not have this option set, an "
1197 "error is reported."
1198 },
1199 { .key = {"nfs.enable-ino32"},
1200 .type = GF_OPTION_TYPE_BOOL,
1201 .description = "For nfs clients or apps that do not support 64-bit "
1202 "inode numbers, use this option to make NFS return "
1203 "32-bit inode numbers instead. Disabled by default, so "
1204 "NFS returns 64-bit inode numbers."
1205 },
1206 { .key = {"rpc.register-with-portmap"},
1207 .type = GF_OPTION_TYPE_BOOL,
1208 .description = "For systems that need to run multiple nfs servers, "
1209 "only one registration is possible with "
1210 "portmap service. Use this option to turn off portmap "
1211 "registration for Gluster NFS. On by default"
1212 },
1213 { .key = {"nfs.port"},
1214 .type = GF_OPTION_TYPE_INT,
1215 .min = 1,
1216 .max = 0xffff,
1217 .description = "Use this option on systems that need Gluster NFS to "
1218 "be associated with a non-default port number."
1219 },
1220 { .key = {"nfs.mem-factor"},
1221 .type = GF_OPTION_TYPE_INT,
1222 .min = 1,
1223 .max = 1024,
1224 .description = "Use this option to make NFS be faster on systems by "
1225 "using more memory. This option specifies a multiple "
1226 "that determines the total amount of memory used. "
1227 "Default value is 15. Increase to use more memory in "
1228 "order to improve performance for certain use cases."
1229 "Please consult gluster-users list before using this "
1230 "option."
1231 },
1232 { .key = {"nfs.*.disable"},
1233 .type = GF_OPTION_TYPE_BOOL,
1234 .description = "This option is used to start or stop NFS server"
1235 "for individual volume."
1236 },
1237
1238 { .key = {"nfs.nlm"},
1239 .type = GF_OPTION_TYPE_BOOL,
1240 .description = "This option, if set to 'off', disables NLM server "
1241 "by not registering the service with the portmapper."
1242 " Set it to 'on' to re-enable it. Default value: 'on'"
1243 },
1244
1245 { .key = {"nfs.mount-udp"},
1246 .type = GF_OPTION_TYPE_BOOL,
1247 .description = "set the option to 'on' to enable mountd on UDP. "
1248 "Required for some Solaris and AIX NFS clients. "
1249 "The need for enabling this option often depends "
1250 "on the usage of NLM."
1251 },
1252 { .key = {OPT_SERVER_AUX_GIDS"nfs.server-aux-gids"},
1253 .type = GF_OPTION_TYPE_BOOL,
1254 .default_value = "off",
1255 .description = "Let the server look up which groups a user belongs "
1256 "to, overwriting the list passed from the client. "
1257 "This enables support for group lists longer than "
1258 "can be passed through the NFS protocol, but is not "
1259 "secure unless users and groups are well synchronized "
1260 "between clients and servers."
1261 },
1262 { .key = {OPT_SERVER_GID_CACHE_TIMEOUT"nfs.server.aux-gid-timeout"},
1263 .type = GF_OPTION_TYPE_INT,
1264 .min = 0,
1265 .max = 3600,
1266 .default_value = "5",
1267 .description = "Number of seconds to cache auxiliary-GID data, when "
1268 OPT_SERVER_AUX_GIDS"nfs.server-aux-gids" " is set."
1269 },
1270
1271 { .key = {NULL((void*)0)} },
1272};
1273