Whamcloud - gitweb
LU-10378 utils: add formatted printf to lfs find
[fs/lustre-release.git] / lustre / utils / l_foreign_symlink.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program 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 version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2020, Intel Corporation.
24  */
25
26 /*
27  * lustre/utils/l_foreign_symlink.c
28  * Userland helper to provide detailed format items in order to allow for
29  * a fast parsing of foreign symlink LOV/LMV EAs in llite.
30  * Presently, the foreign symlink LOV/LMV EAs format and its translation
31  * in format items is hard-coded, but in the future we may want to make it
32  * smarter and automatize this process by some mean.
33  */
34
35 #include <sys/types.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <libgen.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <limits.h>
45 #include <syslog.h>
46 #include <stdarg.h>
47 #include <fcntl.h>
48 #include <stddef.h>
49 #include <ctype.h>
50 #include <dirent.h>
51 #include <getopt.h>
52
53 #include <libcfs/util/param.h>
54 #include <linux/lustre/lustre_user.h>
55 #include <linux/lustre/lustre_idl.h>
56
57 #define UUID_STRING_LENGTH 36
58 #define MAX_BUF_SIZE 1024
59
60 static char *progname;
61
62 static void errlog(const char *fmt, ...)
63 {
64         va_list args;
65
66         openlog(progname, LOG_PERROR | LOG_PID, LOG_KERN);
67
68         va_start(args, fmt);
69         vsyslog(LOG_ERR, fmt, args);
70         va_end(args);
71
72         closelog();
73 }
74
75 int main(int argc, char **argv)
76 {
77         /* we want to request llite layer to parse each foreign symlink
78          * LOV/LMV EAs with lfm_value of format "<PUUID>:<CUUID>" and
79          * translate it as "<UUID>/<UUID>" relative path.
80          * To do so, will need to pass a serie of 4 items, one for
81          * <PUUID> position and length in lfm_value, one with constant
82          * string "/", one for <CUUID> position and length in lfm_value,
83          * a last one to indicate end of serie.
84          */
85         struct ll_foreign_symlink_upcall_item *items;
86         char *buf;
87         glob_t path;
88         int fd, rc;
89
90         progname = basename(argv[0]);
91
92         if (argc != 2) {
93                 errlog("usage: %s <sbi_sysfs_object_name>\n", argv[0]);
94                 return -1;
95         }
96
97         buf = malloc(MAX_BUF_SIZE);
98         if (buf == NULL) {
99                 errlog("unable to allocate MAX_BUF_SIZE bytes\n");
100                 return -1;
101         }
102
103         /* the number of items is presently limited to MAX_NB_UPCALL_ITEMS */
104
105         /* all items are expected to be on a __u32 boundary by llite */
106
107         /* 1st item to locate <PUUID> */
108         items = (struct ll_foreign_symlink_upcall_item *)buf;
109         items->type = POSLEN_TYPE;
110         items->pos = 0;
111         items->len = UUID_STRING_LENGTH;
112
113         /* 2nd item to store "/" string */
114         items = (struct ll_foreign_symlink_upcall_item *)((char *)items +
115                         POSLEN_ITEM_SZ);
116         items->type = STRING_TYPE;
117         /* NUL byte is not necessary */
118         items->size = strlen("/");
119         memcpy(items->bytestring, "/", strlen("/"));
120         /* space occupied by string will fit on __u32 boundary */
121
122         /* 3rd item to locate <CUUID> */
123         items = (struct ll_foreign_symlink_upcall_item *)((char *)items +
124                 STRING_ITEM_SZ(items->size));
125         items->type = POSLEN_TYPE;
126         items->pos = UUID_STRING_LENGTH + 1;
127         items->len = UUID_STRING_LENGTH;
128
129         /* 4th item is end of buf */
130         items = (struct ll_foreign_symlink_upcall_item *)((char *)items +
131                         POSLEN_ITEM_SZ);
132         items->type = EOB_TYPE;
133
134         /* Send foreign symlink parsing items info to kernelspace */
135         rc = cfs_get_param_paths(&path, "llite/%s/foreign_symlink_upcall_info",
136                                  argv[1]);
137         if (rc != 0) {
138                 errlog("can't get param 'llite/%s/foreign_symlink_upcall_info': %s\n",
139                        argv[1], strerror(errno));
140                 rc = -errno;
141                 goto out;
142         }
143
144         fd = open(path.gl_pathv[0], O_WRONLY);
145         if (fd < 0) {
146                 errlog("can't open file '%s':%s\n", path.gl_pathv[0],
147                        strerror(errno));
148                 rc = -errno;
149                 goto out_param;
150         }
151
152         rc = write(fd, buf, (char *)items + sizeof(items->type) - buf);
153         close(fd);
154         if (rc != (char *)items + sizeof(items->type) - buf) {
155                 errlog("partial write ret %d: %s\n", rc, strerror(errno));
156                 rc = -errno;
157         } else {
158                 rc = 0;
159         }
160
161 out_param:
162         cfs_free_param_data(&path);
163 out:
164         if (isatty(STDIN_FILENO))
165                 /* we are called from the command line */
166                 return rc < 0 ? -rc : rc;
167         else
168                 return rc;
169 }