1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 #include <lustre/lustre_user.h>
40 #define CHECK_DURATION_START \
42 time_t __check_start = time(NULL)
44 #define CHECK_DURATION_END(str, secs) \
45 if (time(NULL) > __check_start + (secs)) \
46 errlog("LONG OP %s: %d elapsed, %d expected\n", str, \
47 time(NULL) - __check_start, secs); \
50 void usage(FILE *out, const char *progname)
52 fprintf(out, "\nusage: %s [-v] {-d | <mdsname>} <uid>\n"
54 "Normally invoked as an upcall from Lustre, set via:\n"
55 " /proc/fs/lustre/mds/{mdsname}/group_upcall\n"
56 "\t-d: debug, print values to stdout instead of Lustre\n"
57 "\t-s: sleep, mlock memory in core and sleep forever\n"
58 "\t-v: verbose, log start/stop to syslog\n",
62 static int compare_u32(const void *v1, const void *v2)
64 return (*(__u32 *)v1 - *(__u32 *)v2);
67 static void errlog(const char *fmt, ...)
73 vsyslog(LOG_NOTICE, fmt, arg);
76 vfprintf(stderr, fmt, carg);
80 int get_groups_local(struct mds_grp_downcall_data **grp)
82 struct mds_grp_downcall_data *param;
83 int i, maxgroups, size;
88 pw = getpwuid((*grp)->mgd_uid);
89 CHECK_DURATION_END("getpwuid", 2);
91 errlog("no such user %u\n", (*grp)->mgd_uid);
92 (*grp)->mgd_err = errno ? errno : EIDRM;
93 return sizeof(*param);
95 (*grp)->mgd_gid = pw->pw_gid;
97 maxgroups = sysconf(_SC_NGROUPS_MAX);
98 size = offsetof(struct mds_grp_downcall_data, mgd_groups[maxgroups]);
101 errlog("fail to alloc %d bytes for uid %u with %d groups\n",
102 size, (*grp)->mgd_uid, maxgroups);
103 return sizeof(*param);
106 memcpy(param, *grp, sizeof(*param));
107 param->mgd_groups[param->mgd_ngroups++] = pw->pw_gid;
109 CHECK_DURATION_START;
110 while ((gr = getgrent())) {
111 if (gr->gr_gid == pw->pw_gid)
115 for (i = 0; gr->gr_mem[i]; i++) {
116 if (strcmp(gr->gr_mem[i], pw->pw_name) == 0) {
117 param->mgd_groups[param->mgd_ngroups++] =
122 if (param->mgd_ngroups == maxgroups)
125 CHECK_DURATION_END("getgrent loop", 3);
127 qsort(param->mgd_groups, param->mgd_ngroups,
128 sizeof(param->mgd_groups[0]), compare_u32);
133 /* Note that we need to make the downcall regardless of error, so that the
134 * MDS doesn't continue to wait on the upcall. */
135 int main(int argc, char **argv)
138 int debug = 0, sleepy = 0, verbose = 0, print_usage = 0;
140 struct mds_grp_downcall_data sparam = { MDS_GRP_DOWNCALL_MAGIC };
141 struct mds_grp_downcall_data *param = &sparam;
142 char pathname[1024], *end, *progname, *mdsname = NULL;
144 progname = strrchr(argv[0], '/');
145 if (progname == NULL)
150 if (strstr(progname, "verbose"))
153 openlog(progname, LOG_PERROR, LOG_AUTHPRIV);
156 while ((c = getopt(argc, argv, "dhsv")) != -1) {
168 errlog("bad parameter '%c'\n", optopt);
176 /* sleep has 0 param, debug has 1 param, upcall has 2 param */
177 if (!sleepy && optind + !sleepy + !debug != argc)
181 usage(stderr, progname);
182 return print_usage > 1 ? EINVAL : 0;
186 param->mgd_uid = strtoul(argv[optind + !debug], &end, 0);
188 errlog("invalid uid '%s'", argv[optind + !debug]);
189 usage(stderr, progname);
193 mdsname = argv[optind];
199 syslog(LOG_DEBUG, "starting l_getgroups(pid %u) for uid %u\n",
200 mypid, param->mgd_uid);
202 CHECK_DURATION_START;
203 size = get_groups_local(¶m);
204 CHECK_DURATION_END("get_groups_local", 10);
207 if (param->mgd_err) {
208 if (param->mgd_err != ENXIO)
209 errlog("error getting uid %d groups: %s\n",
210 param->mgd_uid,strerror(param->mgd_err));
213 printf("uid=%d gid=", param->mgd_uid);
214 for (i = 0; i < param->mgd_ngroups; i++)
215 printf("%s%d", i > 0 ? "," : "",
216 param->mgd_groups[i]);
221 rc = mlockall(MCL_CURRENT);
222 errlog("%s all pages in RAM (pid %u): rc %d\n",
223 rc ? "failed to lock" : "locked", mypid, rc);
226 snprintf(pathname, 1024, "/proc/fs/lustre/mds/%s/group_info",
228 CHECK_DURATION_START;
229 fd = open(pathname, O_WRONLY);
231 errlog("can't open device %s: %s\n",
232 pathname, strerror(errno));
235 rc = write(fd, param, size);
241 CHECK_DURATION_END("group_info write", 1);
244 syslog(LOG_DEBUG, "ending l_getgroups(pid %u) for uid %u\n",
245 mypid, param->mgd_uid);