Whamcloud - gitweb
LU-17402 kernel: update dotdot patch path for RHEL 8.10
[fs/lustre-release.git] / lustre / llite / llite_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  * Foreign symlink implementation.
27  *
28  * Methods in this source file allow to construct a relative path from the
29  * LOV/LMV foreign content, to complement it with a prefix, and then to
30  * expose it to the VFS as a symlink destination.
31  * The default/internal mechanism simply takes the full foreign free string
32  * as the relative path, and for more complex internal formats an upcall has
33  * been implemented to provide format's details (presently just in terms of
34  * constant strings and substrings positions in EA, but this can be enhanced)
35  * to llite layer.
36  */
37
38 #include <linux/fs.h>
39 #include <linux/fs_struct.h>
40 #include <linux/mm.h>
41 #include <linux/stat.h>
42 #include <linux/version.h>
43 #define DEBUG_SUBSYSTEM S_LLITE
44
45 #include "llite_internal.h"
46
47 /* allocate space for "/<prefix>/<suffix>'\0'" and copy prefix in,
48  * returns start position for suffix in *destname
49  * must be called with ll_foreign_symlink_sem locked for read, to
50  * protect against sbi->ll_foreign_symlink_prefix change
51  * on output, provides position where to start prefix complement
52  */
53 static int foreign_symlink_alloc_and_copy_prefix(struct ll_sb_info *sbi,
54                                                  struct inode *inode,
55                                                  char **destname,
56                                                  size_t suffix_size)
57 {
58         size_t prefix_size, full_size;
59
60         ENTRY;
61
62         /* allocate enough for "/<prefix>/<suffix>'\0'" */
63         prefix_size = sbi->ll_foreign_symlink_prefix_size - 1;
64         full_size = suffix_size + prefix_size + 3;
65         if (full_size > PATH_MAX) {
66                 CERROR("%s: inode "DFID": resolved destination path too long\n",
67                        sbi->ll_fsname, PFID(ll_inode2fid(inode)));
68                 RETURN(-EINVAL);
69         }
70         OBD_ALLOC(*destname, full_size);
71         if (*destname == NULL)
72                 RETURN(-ENOMEM);
73
74         memcpy(*destname + 1, sbi->ll_foreign_symlink_prefix,
75                prefix_size);
76         (*destname)[0] = '/';
77         (*destname)[prefix_size + 1] = '/';
78
79         RETURN(prefix_size + 2);
80 }
81
82 /* if no upcall registered, default foreign symlink parsing method
83  * is to use the full lfm_value as a relative path to complement
84  * foreign_prefix
85  */
86 static int ll_foreign_symlink_default_parse(struct ll_sb_info *sbi,
87                                             struct inode *inode,
88                                             struct lov_foreign_md *lfm,
89                                             char **destname)
90 {
91         int suffix_pos;
92
93         down_read(&sbi->ll_foreign_symlink_sem);
94         suffix_pos = foreign_symlink_alloc_and_copy_prefix(sbi, inode,
95                                                            destname,
96                                                            lfm->lfm_length);
97         up_read(&sbi->ll_foreign_symlink_sem);
98
99         if (suffix_pos < 0)
100                 RETURN(suffix_pos);
101
102         memcpy(*destname + suffix_pos, lfm->lfm_value,
103                lfm->lfm_length);
104         (*destname)[suffix_pos + lfm->lfm_length] = '\0';
105
106         RETURN(0);
107 }
108
109 /* if an upcall has been registered, foreign symlink will be
110  * constructed as per upcall provided format
111  * presently we only support a serie of constant strings and sub-strings
112  * to be taken from lfm_value content
113  */
114 static int ll_foreign_symlink_upcall_parse(struct ll_sb_info *sbi,
115                                            struct inode *inode,
116                                            struct lov_foreign_md *lfm,
117                                            char **destname)
118 {
119         int pos = 0, suffix_pos = -1, items_size = 0;
120         struct ll_foreign_symlink_upcall_item *foreign_symlink_items =
121                         sbi->ll_foreign_symlink_upcall_items;
122         int i = 0, rc = 0;
123
124         ENTRY;
125
126         down_read(&sbi->ll_foreign_symlink_sem);
127
128         /* compute size of relative path of destination path
129          * could be done once during upcall items/infos reading
130          * and stored as new ll_sb_info field
131          */
132         for (i = 0; i < sbi->ll_foreign_symlink_upcall_nb_items; i++) {
133                 switch (foreign_symlink_items[i].type) {
134                 case STRING_TYPE:
135                         items_size += foreign_symlink_items[i].size;
136                         break;
137                 case POSLEN_TYPE:
138                         items_size += foreign_symlink_items[i].len;
139                         break;
140                 case EOB_TYPE:
141                         /* should be the last item */
142                         break;
143                 default:
144                         CERROR("%s: unexpected type '%u' found in items\n",
145                                sbi->ll_fsname, foreign_symlink_items[i].type);
146                         GOTO(failed, rc = -EINVAL);
147                 }
148         }
149
150         suffix_pos = foreign_symlink_alloc_and_copy_prefix(sbi, inode, destname,
151                                                            items_size);
152         if (suffix_pos < 0)
153                 GOTO(failed, rc = suffix_pos);
154
155         /* rescan foreign_symlink_items[] to create faked symlink dest path */
156         i = 0;
157         while (foreign_symlink_items[i].type != EOB_TYPE) {
158                 if (foreign_symlink_items[i].type == STRING_TYPE) {
159                         memcpy(*destname + suffix_pos + pos,
160                                foreign_symlink_items[i].string,
161                                foreign_symlink_items[i].size);
162                         pos += foreign_symlink_items[i].size;
163                 } else if (foreign_symlink_items[i].type == POSLEN_TYPE) {
164                         if (lfm->lfm_length < foreign_symlink_items[i].pos +
165                                               foreign_symlink_items[i].len) {
166                                 CERROR("%s:  "DFID" foreign EA too short to find (%u,%u) item\n",
167                                        sbi->ll_fsname,
168                                        PFID(ll_inode2fid(inode)),
169                                        foreign_symlink_items[i].pos,
170                                        foreign_symlink_items[i].len);
171                                 GOTO(failed, rc = -EINVAL);
172                         }
173                         memcpy(*destname + suffix_pos + pos,
174                                lfm->lfm_value + foreign_symlink_items[i].pos,
175                                foreign_symlink_items[i].len);
176                         pos += foreign_symlink_items[i].len;
177                 } else {
178                         CERROR("%s: unexpected type '%u' found in items\n",
179                                sbi->ll_fsname, foreign_symlink_items[i].type);
180                         GOTO(failed, rc = -EINVAL);
181                 }
182                 i++;
183         }
184 failed:
185         up_read(&sbi->ll_foreign_symlink_sem);
186
187         if (rc != 0 && suffix_pos >= 0) {
188                 OBD_FREE_LARGE(*destname, suffix_pos + items_size);
189                 *destname = NULL;
190         }
191
192         RETURN(rc);
193 }
194
195 static int ll_foreign_symlink_parse(struct ll_sb_info *sbi,
196                                     struct inode *inode,
197                                     struct lov_foreign_md *lfm,
198                                     char **destname)
199 {
200         int rc;
201
202         /* if no user-land upcall registered, assuming whole free field
203          * of foreign LOV is relative path of faked symlink destination,
204          * to be completed by prefix
205          */
206         if (!test_bit(LL_SBI_FOREIGN_SYMLINK_UPCALL, sbi->ll_flags))
207                 rc = ll_foreign_symlink_default_parse(sbi, inode, lfm,
208                                                       destname);
209         else /* upcall is available */
210                 rc = ll_foreign_symlink_upcall_parse(sbi, inode, lfm,
211                                                      destname);
212         return rc;
213 }
214
215 /* Don't need lli_size_mutex locked as LOV/LMV are EAs
216  * and should not be stored in data blocks
217  */
218 static int ll_foreign_readlink_internal(struct inode *inode, char **symname)
219 {
220         struct ll_inode_info *lli = ll_i2info(inode);
221         struct ll_sb_info *sbi = ll_i2sbi(inode);
222         struct lmv_stripe_object *lsm_obj = NULL;
223         struct lov_foreign_md *lfm = NULL;
224         char *destname = NULL;
225         size_t lfm_size = 0;
226         int rc;
227
228         ENTRY;
229
230         if (S_ISREG(inode->i_mode)) {
231                 struct cl_object *obj = lli->lli_clob;
232                 struct cl_layout cl = {
233                         .cl_buf.lb_len = 0, /* to get real size */
234                 };
235                 struct lu_env *env;
236                 u16 refcheck;
237
238                 if (!obj) {
239                         CERROR("%s: inode "DFID": can not get layout, no cl_object\n",
240                                sbi->ll_fsname, PFID(ll_inode2fid(inode)));
241                         GOTO(failed, rc = -EINVAL);
242                 }
243
244                 env = cl_env_get(&refcheck);
245                 if (IS_ERR(env))
246                         RETURN(PTR_ERR(env));
247                 /* get layout size */
248                 rc = cl_object_layout_get(env, obj, &cl);
249                 if (rc <= 0) {
250                         CERROR("%s: inode "DFID": error trying to get layout size : %d\n",
251                                sbi->ll_fsname, PFID(ll_inode2fid(inode)), rc);
252                         cl_env_put(env, &refcheck);
253                         RETURN(rc);
254                 }
255                 OBD_ALLOC(lfm, rc);
256                 if (!lfm) {
257                         CERROR("%s: inode "DFID": can not allocate enough mem to get layout\n",
258                                sbi->ll_fsname, PFID(ll_inode2fid(inode)));
259                         cl_env_put(env, &refcheck);
260                         RETURN(-ENOMEM);
261                 }
262                 cl.cl_buf.lb_len = rc;
263                 cl.cl_buf.lb_buf = lfm;
264                 /* get layout */
265                 rc = cl_object_layout_get(env, obj, &cl);
266                 if (rc <= 0) {
267                         CERROR("%s: inode "DFID": error trying to get layout : %d\n",
268                                sbi->ll_fsname, PFID(ll_inode2fid(inode)), rc);
269                         OBD_FREE(lfm, cl.cl_buf.lb_len);
270                         cl_env_put(env, &refcheck);
271                         RETURN(rc);
272                 }
273                 lfm_size = cl.cl_buf.lb_len;
274                 cl_env_put(env, &refcheck);
275         } else if (S_ISDIR(inode->i_mode)) {
276                 down_read(&lli->lli_lsm_sem);
277
278                 /* should be casted lmv_foreign_md, but it is ok as both foreign LOV
279                  * and LMV formats are identical, and then we also only need
280                  * one set of parsing routines for both foreign files and dirs!
281                  */
282                 lsm_obj = lmv_stripe_object_get(lli->lli_lsm_obj);
283                 up_read(&lli->lli_lsm_sem);
284
285                 if (lsm_obj != NULL) {
286                         lfm = (struct lov_foreign_md *)&lsm_obj->lso_lfm;
287                         CDEBUG(D_INFO, "%s: inode "DFID": LMV cached found\n",
288                                sbi->ll_fsname, PFID(ll_inode2fid(inode)));
289                 } else {
290                         CERROR("%s: inode "DFID": cannot get layout, no LMV cached\n",
291                                sbi->ll_fsname, PFID(ll_inode2fid(inode)));
292                         GOTO(failed, rc = -EINVAL);
293                 }
294         } else {
295                 CERROR("%s: inode "DFID": not a regular file nor directory\n",
296                        sbi->ll_fsname, PFID(ll_inode2fid(inode)));
297                 GOTO(failed, rc = -EINVAL);
298         }
299
300         /* XXX no assert nor double check of magic, length and type ? */
301
302         rc = ll_foreign_symlink_parse(sbi, inode, lfm, &destname);
303
304 failed:
305         if (S_ISDIR(inode->i_mode))
306                 lmv_stripe_object_put(&lsm_obj);
307
308         if (S_ISREG(inode->i_mode) && lfm)
309                 OBD_FREE(lfm, lfm_size);
310
311         if (!rc) {
312                 *symname = destname;
313                 CDEBUG(D_INFO,
314                        "%s: inode "DFID": faking symlink to dest '%s'\n",
315                        sbi->ll_fsname, PFID(ll_inode2fid(inode)), destname);
316         }
317
318         RETURN(rc);
319 }
320
321 #ifdef HAVE_SYMLINK_OPS_USE_NAMEIDATA
322 static void ll_foreign_put_link(struct dentry *dentry,
323                         struct nameidata *nd, void *cookie)
324 #else
325 # ifdef HAVE_IOP_GET_LINK
326 static void ll_foreign_put_link(void *cookie)
327 # else
328 static void ll_foreign_put_link(struct inode *unused, void *cookie)
329 # endif
330 #endif
331 {
332         /* to avoid allocating an unnecessary big buffer, and since ways to
333          * build the symlink path from foreign LOV/LMV can be multiple and
334          * not constant. So it size is not known and we need to use
335          * strlen(cookie)+1 to determine its size and to avoid false positive
336          * to be reported by memory leak check code
337          */
338         OBD_FREE_LARGE(cookie, strlen(cookie) + 1);
339 }
340
341 #ifdef HAVE_SYMLINK_OPS_USE_NAMEIDATA
342 static void *ll_foreign_follow_link(struct dentry *dentry,
343                                       struct nameidata *nd)
344 {
345         struct inode *inode = dentry->d_inode;
346         int rc;
347         char *symname = NULL;
348
349         ENTRY;
350
351         CDEBUG(D_VFSTRACE, "VFS Op\n");
352         /*
353          * Limit the recursive symlink depth to 5 instead of default
354          * 8 links when kernel has 4k stack to prevent stack overflow.
355          * For 8k stacks we need to limit it to 7 for local servers.
356          */
357         if (THREAD_SIZE < 8192 && current->link_count >= 6)
358                 rc = -ELOOP;
359         else if (THREAD_SIZE == 8192 && current->link_count >= 8)
360                 rc = -ELOOP;
361         else
362                 rc = ll_foreign_readlink_internal(inode, &symname);
363
364         if (rc)
365                 symname = ERR_PTR(rc);
366
367         nd_set_link(nd, symname);
368         RETURN(symname);
369 }
370
371 #elif defined(HAVE_IOP_GET_LINK)
372 static const char *ll_foreign_get_link(struct dentry *dentry,
373                                        struct inode *inode,
374                                        struct delayed_call *done)
375 {
376         char *symname = NULL;
377         int rc;
378
379         ENTRY;
380         CDEBUG(D_VFSTRACE, "VFS Op\n");
381         if (!dentry)
382                 RETURN(ERR_PTR(-ECHILD));
383         rc = ll_foreign_readlink_internal(inode, &symname);
384
385         /*
386          * symname must be freed when we are done
387          *
388          * XXX we may avoid the need to do so if we use
389          * lli_symlink_name cache to retain symname and
390          * let ll_clear_inode free it...
391          */
392         set_delayed_call(done, ll_foreign_put_link, symname);
393         RETURN(rc ? ERR_PTR(rc) : symname);
394 }
395
396 # else /* !HAVE_IOP_GET_LINK */
397 static const char *ll_foreign_follow_link(struct dentry *dentry,
398                                             void **cookie)
399 {
400         struct inode *inode = d_inode(dentry);
401         char *symname = NULL;
402         int rc;
403
404         ENTRY;
405
406         CDEBUG(D_VFSTRACE, "VFS Op\n");
407         rc = ll_foreign_readlink_internal(inode, &symname);
408         if (rc < 0)
409                 return ERR_PTR(rc);
410
411         /* XXX need to also return symname in cookie in order to delay
412          * its release ??
413          */
414
415         RETURN(symname);
416 }
417
418 #endif /* HAVE_SYMLINK_OPS_USE_NAMEIDATA, HAVE_IOP_GET_LINK */
419
420 /*
421  * Should only be called for already in-use/cache foreign dir inode
422  * when foreign fake-symlink behaviour has been enabled afterward
423  */
424 static struct dentry *ll_foreign_dir_lookup(struct inode *parent,
425                                          struct dentry *dentry,
426                                          unsigned int flags)
427 {
428         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s, dir="DFID"(%p)\n",
429                dentry->d_name.len, dentry->d_name.name,
430                PFID(ll_inode2fid(parent)), parent);
431
432         return ERR_PTR(-ENODATA);
433 }
434
435 static bool has_same_mount_namespace(struct ll_sb_info *sbi)
436 {
437         bool same;
438
439         same = (sbi->ll_mnt_ns == current->nsproxy->mnt_ns);
440         if (!same)
441                 LCONSOLE_WARN("%s: client mount %s and '%s.%d' not in same mnt-namespace\n",
442                               sbi->ll_fsname, sbi->ll_kset.kobj.name,
443                               current->comm, current->pid);
444
445         return same;
446 }
447
448 ssize_t foreign_symlink_enable_show(struct kobject *kobj,
449                                     struct attribute *attr, char *buf)
450 {
451         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
452                                               ll_kset.kobj);
453
454         return snprintf(buf, PAGE_SIZE, "%d\n",
455                         test_bit(LL_SBI_FOREIGN_SYMLINK, sbi->ll_flags));
456 }
457
458 /*
459  * XXX
460  * There should be already in-use/cached inodes of foreign files/dirs who
461  * will not-be/continue-to-be handled as fake-symlink, depending if
462  * feature is being enabled/disabled, until being revalidated.
463  * Also, does it require sbi->ll_lock protection ?
464  */
465 ssize_t foreign_symlink_enable_store(struct kobject *kobj,
466                                      struct attribute *attr,
467                                      const char *buffer, size_t count)
468 {
469         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
470                                               ll_kset.kobj);
471         unsigned int val;
472         int rc;
473
474         if (!has_same_mount_namespace(sbi))
475                 return -EINVAL;
476
477         rc = kstrtouint(buffer, 10, &val);
478         if (rc)
479                 return rc;
480
481         if (val)
482                 set_bit(LL_SBI_FOREIGN_SYMLINK, sbi->ll_flags);
483         else
484                 clear_bit(LL_SBI_FOREIGN_SYMLINK, sbi->ll_flags);
485
486         return count;
487 }
488
489 ssize_t foreign_symlink_prefix_show(struct kobject *kobj,
490                                     struct attribute *attr, char *buf)
491 {
492         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
493                                               ll_kset.kobj);
494         ssize_t size;
495
496         down_read(&sbi->ll_foreign_symlink_sem);
497         size = snprintf(buf, PAGE_SIZE, "%s\n", sbi->ll_foreign_symlink_prefix);
498         up_read(&sbi->ll_foreign_symlink_sem);
499
500         return size;
501 }
502
503 ssize_t foreign_symlink_prefix_store(struct kobject *kobj,
504                                      struct attribute *attr,
505                                      const char *buffer, size_t count)
506 {
507         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
508                                               ll_kset.kobj);
509         char *new, *old;
510         size_t new_len, old_len;
511
512         if (!has_same_mount_namespace(sbi))
513                 return -EINVAL;
514
515         /* XXX strip buffer of any CR/LF,space,... ?? */
516
517         /* check buffer looks like a valid absolute path */
518         if (*buffer != '/') {
519                 CERROR("foreign symlink prefix must be an absolute path\n");
520                 return -EINVAL;
521         }
522         new_len = strnlen(buffer, count);
523         if (new_len < count)
524                 CDEBUG(D_INFO, "NUL byte found in %zu bytes\n", count);
525         if (new_len > PATH_MAX) {
526                 CERROR("%s: foreign symlink prefix length %zu > PATH_MAX\n",
527                        sbi->ll_fsname, new_len);
528                 return -EINVAL;
529         }
530         OBD_ALLOC(new, new_len + 1);
531         if (new == NULL) {
532                 CERROR("%s: can not allocate space for foreign path prefix\n",
533                        sbi->ll_fsname);
534                 return -ENOSPC;
535         }
536
537         down_write(&sbi->ll_foreign_symlink_sem);
538         old_len = sbi->ll_foreign_symlink_prefix_size;
539         old = sbi->ll_foreign_symlink_prefix;
540         memcpy(new, buffer, new_len);
541         *(new + new_len) = '\0';
542
543         sbi->ll_foreign_symlink_prefix = new;
544         sbi->ll_foreign_symlink_prefix_size = new_len + 1;
545         up_write(&sbi->ll_foreign_symlink_sem);
546
547         if (old)
548                 OBD_FREE(old, old_len);
549
550         return new_len;
551 }
552
553 ssize_t foreign_symlink_upcall_show(struct kobject *kobj,
554                                     struct attribute *attr, char *buf)
555 {
556         ssize_t size;
557         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
558                                               ll_kset.kobj);
559
560         down_read(&sbi->ll_foreign_symlink_sem);
561         size = snprintf(buf, PAGE_SIZE, "%s\n", sbi->ll_foreign_symlink_upcall);
562         up_read(&sbi->ll_foreign_symlink_sem);
563
564         return size;
565 }
566
567 ssize_t foreign_symlink_upcall_store(struct kobject *kobj,
568                                      struct attribute *attr,
569                                      const char *buffer, size_t count)
570 {
571         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
572                                               ll_kset.kobj);
573         char *old = NULL, *new = NULL;
574         size_t new_len;
575
576         if (!has_same_mount_namespace(sbi))
577                 return -EINVAL;
578
579         /* XXX strip buffer of any CR/LF,space,... ?? */
580
581         /* check buffer looks like a valid absolute path */
582         if (*buffer != '/' && strcmp(buffer, "none")) {
583                 CERROR("foreign symlink upcall must be an absolute path\n");
584                 return -EINVAL;
585         }
586         new_len = strnlen(buffer, count);
587         if (new_len < count)
588                 CDEBUG(D_INFO, "NULL byte found in %zu bytes\n", count);
589         if (new_len > PATH_MAX) {
590                 CERROR("%s: foreign symlink upcall path length %zu > PATH_MAX\n",
591                        sbi->ll_fsname, new_len);
592                 return -EINVAL;
593         }
594
595         OBD_ALLOC(new, new_len + 1);
596         if (new == NULL) {
597                 CERROR("%s: can not allocate space for foreign symlink upcall path\n",
598                        sbi->ll_fsname);
599                 return -ENOSPC;
600         }
601         memcpy(new, buffer, new_len);
602         *(new + new_len) = '\0';
603
604         down_write(&sbi->ll_foreign_symlink_sem);
605         old = sbi->ll_foreign_symlink_upcall;
606
607         sbi->ll_foreign_symlink_upcall = new;
608         /* LL_SBI_FOREIGN_SYMLINK_UPCALL will be set by
609          * foreign_symlink_upcall_info_store() upon valid being provided
610          * by upcall
611          * XXX there is a potential race if there are multiple concurent
612          * attempts to set upcall path and execution occur in different
613          * order, we may end up using the format provided by a different
614          * upcall than the one set in ll_foreign_symlink_upcall
615          */
616         clear_bit(LL_SBI_FOREIGN_SYMLINK_UPCALL, sbi->ll_flags);
617         up_write(&sbi->ll_foreign_symlink_sem);
618
619         if (strcmp(new, "none")) {
620                 char *argv[] = {
621                           [0] = new,
622                           /* sbi sysfs object name */
623                           [1] = (char *)sbi->ll_kset.kobj.name,
624                           [2] = NULL
625                 };
626                 char *envp[] = {
627                           [0] = "HOME=/",
628                           [1] = "PATH=/sbin:/usr/sbin",
629                           [2] = NULL
630                 };
631                 int rc;
632
633                 rc = call_usermodehelper(new, argv, envp, UMH_WAIT_EXEC);
634                 if (rc < 0)
635                         CERROR("%s: error invoking foreign symlink upcall %s: rc %d\n",
636                                sbi->ll_fsname, new, rc);
637                 else
638                         CDEBUG(D_INFO, "%s: invoked upcall %s\n",
639                                sbi->ll_fsname, new);
640         }
641
642         if (old)
643                 OBD_FREE_LARGE(old, strlen(old) + 1);
644
645         return new_len;
646 }
647
648 /* foreign_symlink_upcall_info_store() stores format items in
649  * foreign_symlink_items[], and foreign_symlink_upcall_parse()
650  * uses it to parse each foreign symlink LOV/LMV EAs
651  */
652 ssize_t foreign_symlink_upcall_info_store(struct kobject *kobj,
653                                      struct attribute *attr,
654                                      const char *buffer, size_t count)
655 {
656         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
657                                               ll_kset.kobj);
658         struct ll_foreign_symlink_upcall_item items[MAX_NB_UPCALL_ITEMS], *item;
659         struct ll_foreign_symlink_upcall_item *new_items, *old_items;
660         size_t remaining = count;
661         int nb_items = 0, old_nb_items, i, rc = 0;
662
663         ENTRY;
664
665         if (!has_same_mount_namespace(sbi))
666                 return -EINVAL;
667
668         /* parse buffer to check validity of infos and fill symlink format
669          * descriptors
670          */
671
672         if (count % sizeof(__u32) != 0) {
673                 CERROR("%s: invalid size '%zu' of infos buffer returned by foreign symlink upcall\n",
674                        sbi->ll_fsname, count);
675                 RETURN(-EINVAL);
676         }
677
678         /* evaluate number of items provided */
679         while (remaining > 0) {
680                 item = (struct ll_foreign_symlink_upcall_item *)
681                                 &buffer[count - remaining];
682                 switch (item->type) {
683                 case STRING_TYPE: {
684                         /* a constant string following */
685                         if (item->size >= remaining -
686                             offsetof(struct ll_foreign_symlink_upcall_item,
687                                      bytestring) - sizeof(item->type)) {
688                                 /* size of string must not overflow remaining
689                                  * bytes minus EOB_TYPE item
690                                  */
691                                 CERROR("%s: constant string too long in infos buffer returned by foreign symlink upcall\n",
692                                        sbi->ll_fsname);
693                                 GOTO(failed, rc = -EINVAL);
694                         }
695                         OBD_ALLOC(items[nb_items].string,
696                                   item->size);
697                         if (items[nb_items].string == NULL) {
698                                 CERROR("%s: constant string allocation has failed for constant string of size %zu\n",
699                                        sbi->ll_fsname, item->size);
700                                 GOTO(failed, rc = -ENOMEM);
701                         }
702                         memcpy(items[nb_items].string,
703                                item->bytestring, item->size);
704                         items[nb_items].size = item->size;
705                         /* string items to fit on __u32 boundary */
706                         remaining = remaining - STRING_ITEM_SZ(item->size);
707                         break;
708                 }
709                 case POSLEN_TYPE: {
710                         /* a tuple (pos,len) following to delimit a sub-string
711                          * in lfm_value
712                          */
713                         items[nb_items].pos = item->pos;
714                         items[nb_items].len = item->len;
715                         remaining -= POSLEN_ITEM_SZ;
716                         break;
717                 }
718                 case EOB_TYPE:
719                         if (remaining != sizeof(item->type)) {
720                                 CERROR("%s: early end of infos buffer returned by foreign symlink upcall\n",
721                                        sbi->ll_fsname);
722                                 GOTO(failed, rc = -EINVAL);
723                         }
724                         remaining -= sizeof(item->type);
725                         break;
726                 default:
727                         CERROR("%s: wrong type '%u' encountered at pos %zu , with %zu remaining bytes, in infos buffer returned by foreign symlink upcall\n",
728                                sbi->ll_fsname, (__u32)buffer[count - remaining],
729                                count - remaining, remaining);
730                         GOTO(failed, rc = -EINVAL);
731                 }
732
733                 items[nb_items].type = item->type;
734                 nb_items++;
735                 if (nb_items >= MAX_NB_UPCALL_ITEMS) {
736                         CERROR("%s: too many items in infos buffer returned by foreign symlink upcall\n",
737                                sbi->ll_fsname);
738                         GOTO(failed, rc = -EINVAL);
739                 }
740         }
741         /* valid format has been provided by foreign symlink user upcall */
742         OBD_ALLOC_LARGE(new_items, nb_items *
743                         sizeof(struct ll_foreign_symlink_upcall_item));
744         if (new_items == NULL) {
745                 CERROR("%s: constant string allocation has failed for constant string of size %zu\n",
746                        sbi->ll_fsname, nb_items *
747                         sizeof(struct ll_foreign_symlink_upcall_item));
748                 GOTO(failed, rc = -ENOMEM);
749         }
750         for (i = 0; i < nb_items; i++)
751                 *((struct ll_foreign_symlink_upcall_item *)new_items + i) =
752                         items[i];
753
754         down_write(&sbi->ll_foreign_symlink_sem);
755         old_items = sbi->ll_foreign_symlink_upcall_items;
756         old_nb_items = sbi->ll_foreign_symlink_upcall_nb_items;
757         sbi->ll_foreign_symlink_upcall_items = new_items;
758         sbi->ll_foreign_symlink_upcall_nb_items = nb_items;
759         set_bit(LL_SBI_FOREIGN_SYMLINK_UPCALL, sbi->ll_flags);
760         up_write(&sbi->ll_foreign_symlink_sem);
761
762         /* free old_items */
763         if (old_items != NULL) {
764                 for (i = 0 ; i < old_nb_items; i++)
765                         if (old_items[i].type == STRING_TYPE)
766                                 OBD_FREE(old_items[i].string,
767                                          old_items[i].size);
768
769                 OBD_FREE_LARGE(old_items, old_nb_items *
770                                sizeof(struct ll_foreign_symlink_upcall_item));
771         }
772
773 failed:
774         /* clean items[] and free any strings */
775         if (rc != 0) {
776                 for (i = 0; i < nb_items; i++) {
777                         switch (items[i].type) {
778                         case STRING_TYPE:
779                                 OBD_FREE(items[i].string, items[i].size);
780                                 items[i].string = NULL;
781                                 items[i].size = 0;
782                                 break;
783                         case POSLEN_TYPE:
784                                 items[i].pos = 0;
785                                 items[i].len = 0;
786                                 break;
787                         case EOB_TYPE:
788                                 break;
789                         default:
790                                 CERROR("%s: wrong '%u'type encountered in foreign symlink upcall items\n",
791                                        sbi->ll_fsname, items[i].type);
792                                 GOTO(failed, rc = -EINVAL);
793                                 break;
794                         }
795                         items[i].type = 0;
796                 }
797         }
798
799         RETURN(rc == 0 ? count : rc);
800 }
801
802 /* foreign fake-symlink version of ll_getattr() */
803 #if defined(HAVE_USER_NAMESPACE_ARG)
804 static int ll_foreign_symlink_getattr(struct mnt_idmap *map,
805                                       const struct path *path,
806                                       struct kstat *stat, u32 request_mask,
807                                       unsigned int flags)
808 {
809         return ll_getattr_dentry(path->dentry, stat, request_mask, flags,
810                                  true);
811 }
812 #elif defined(HAVE_INODEOPS_ENHANCED_GETATTR)
813 static int ll_foreign_symlink_getattr(const struct path *path,
814                                       struct kstat *stat, u32 request_mask,
815                                       unsigned int flags)
816 {
817         return ll_getattr_dentry(path->dentry, stat, request_mask, flags,
818                                  true);
819 }
820 #else
821 static int ll_foreign_symlink_getattr(struct vfsmount *mnt, struct dentry *de,
822                                       struct kstat *stat)
823 {
824         return ll_getattr_dentry(de, stat, STATX_BASIC_STATS,
825                                  AT_STATX_SYNC_AS_STAT, true);
826 }
827 #endif
828
829 struct inode_operations ll_foreign_file_symlink_inode_operations = {
830 #ifdef HAVE_IOP_GENERIC_READLINK
831         .readlink       = generic_readlink,
832 #endif
833         .setattr        = ll_setattr,
834 #ifdef HAVE_IOP_GET_LINK
835         .get_link       = ll_foreign_get_link,
836 #else
837         .follow_link    = ll_foreign_follow_link,
838         /* .put_link method required since need to release symlink copy buf */
839         .put_link       = ll_foreign_put_link,
840 #endif
841         .getattr        = ll_foreign_symlink_getattr,
842         .permission     = ll_inode_permission,
843 #ifdef HAVE_IOP_XATTR
844         .setxattr       = ll_setxattr,
845         .getxattr       = ll_getxattr,
846         .removexattr    = ll_removexattr,
847 #endif
848         .listxattr      = ll_listxattr,
849 };
850
851 struct inode_operations ll_foreign_dir_symlink_inode_operations = {
852         .lookup         = ll_foreign_dir_lookup,
853 #ifdef HAVE_IOP_GENERIC_READLINK
854         .readlink       = generic_readlink,
855 #endif
856         .setattr        = ll_setattr,
857 #ifdef HAVE_IOP_GET_LINK
858         .get_link       = ll_foreign_get_link,
859 #else
860         .follow_link    = ll_foreign_follow_link,
861         .put_link       = ll_foreign_put_link,
862 #endif
863         .getattr        = ll_foreign_symlink_getattr,
864         .permission     = ll_inode_permission,
865 #ifdef HAVE_IOP_XATTR
866         .setxattr       = ll_setxattr,
867         .getxattr       = ll_getxattr,
868         .removexattr    = ll_removexattr,
869 #endif
870         .listxattr      = ll_listxattr,
871 };