4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (c) 2020, Intel Corporation.
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.
35 #include <sys/types.h>
53 #include <libcfs/util/param.h>
54 #include <linux/lustre/lustre_user.h>
55 #include <linux/lustre/lustre_idl.h>
57 #define UUID_STRING_LENGTH 36
58 #define MAX_BUF_SIZE 1024
60 static char *progname;
62 static void errlog(const char *fmt, ...)
66 openlog(progname, LOG_PERROR | LOG_PID, LOG_KERN);
69 vsyslog(LOG_ERR, fmt, args);
75 int main(int argc, char **argv)
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.
85 struct ll_foreign_symlink_upcall_item *items;
90 progname = basename(argv[0]);
93 errlog("usage: %s <sbi_sysfs_object_name>\n", argv[0]);
97 buf = malloc(MAX_BUF_SIZE);
99 errlog("unable to allocate MAX_BUF_SIZE bytes\n");
103 /* the number of items is presently limited to MAX_NB_UPCALL_ITEMS */
105 /* all items are expected to be on a __u32 boundary by llite */
107 /* 1st item to locate <PUUID> */
108 items = (struct ll_foreign_symlink_upcall_item *)buf;
109 items->type = POSLEN_TYPE;
111 items->len = UUID_STRING_LENGTH;
113 /* 2nd item to store "/" string */
114 items = (struct ll_foreign_symlink_upcall_item *)((char *)items +
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 */
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;
129 /* 4th item is end of buf */
130 items = (struct ll_foreign_symlink_upcall_item *)((char *)items +
132 items->type = EOB_TYPE;
134 /* Send foreign symlink parsing items info to kernelspace */
135 rc = cfs_get_param_paths(&path, "llite/%s/foreign_symlink_upcall_info",
138 errlog("can't get param 'llite/%s/foreign_symlink_upcall_info': %s\n",
139 argv[1], strerror(errno));
144 fd = open(path.gl_pathv[0], O_WRONLY);
146 errlog("can't open file '%s':%s\n", path.gl_pathv[0],
152 rc = write(fd, buf, (char *)items + sizeof(items->type) - buf);
154 if (rc != (char *)items + sizeof(items->type) - buf) {
155 errlog("partial write ret %d: %s\n", rc, strerror(errno));
162 cfs_free_param_data(&path);
164 if (isatty(STDIN_FILENO))
165 /* we are called from the command line */
166 return rc < 0 ? -rc : rc;