Whamcloud - gitweb
LU-14644 vvp: wait for nrpages to be updated
[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 (!(sbi->ll_flags & LL_SBI_FOREIGN_SYMLINK_UPCALL))
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 lov_foreign_md *lfm = NULL;
223         char *destname = NULL;
224         size_t lfm_size = 0;
225         int rc;
226
227         ENTRY;
228
229         if (S_ISREG(inode->i_mode)) {
230                 struct cl_object *obj = lli->lli_clob;
231                 struct cl_layout cl = {
232                         .cl_buf.lb_len = 0, /* to get real size */
233                 };
234                 struct lu_env *env;
235                 u16 refcheck;
236
237                 if (!obj) {
238                         CERROR("%s: inode "DFID": can not get layout, no cl_object\n",
239                                sbi->ll_fsname, PFID(ll_inode2fid(inode)));
240                         GOTO(failed, rc = -EINVAL);
241                 }
242
243                 env = cl_env_get(&refcheck);
244                 if (IS_ERR(env))
245                         RETURN(PTR_ERR(env));
246                 /* get layout size */
247                 rc = cl_object_layout_get(env, obj, &cl);
248                 if (rc <= 0) {
249                         CERROR("%s: inode "DFID": error trying to get layout size : %d\n",
250                                sbi->ll_fsname, PFID(ll_inode2fid(inode)), rc);
251                         cl_env_put(env, &refcheck);
252                         RETURN(rc);
253                 }
254                 OBD_ALLOC(lfm, rc);
255                 if (!lfm) {
256                         CERROR("%s: inode "DFID": can not allocate enough mem to get layout\n",
257                                sbi->ll_fsname, PFID(ll_inode2fid(inode)));
258                         cl_env_put(env, &refcheck);
259                         RETURN(-ENOMEM);
260                 }
261                 cl.cl_buf.lb_len = rc;
262                 cl.cl_buf.lb_buf = lfm;
263                 /* get layout */
264                 rc = cl_object_layout_get(env, obj, &cl);
265                 if (rc <= 0) {
266                         CERROR("%s: inode "DFID": error trying to get layout : %d\n",
267                                sbi->ll_fsname, PFID(ll_inode2fid(inode)), rc);
268                         OBD_FREE(lfm, cl.cl_buf.lb_len);
269                         cl_env_put(env, &refcheck);
270                         RETURN(rc);
271                 }
272                 lfm_size = cl.cl_buf.lb_len;
273                 cl_env_put(env, &refcheck);
274         } else if (S_ISDIR(inode->i_mode)) {
275                 down_read(&lli->lli_lsm_sem);
276
277                 /* should be casted lmv_foreign_md, but it is ok as both foreign LOV
278                  * and LMV formats are identical, and then we also only need
279                  * one set of parsing routines for both foreign files and dirs!
280                  */
281                 lfm = (struct lov_foreign_md *)(lli->lli_lsm_md);
282                 if (lfm != NULL) {
283                         CDEBUG(D_INFO, "%s: inode "DFID": LMV cached found\n",
284                                sbi->ll_fsname, PFID(ll_inode2fid(inode)));
285                 } else {
286                         CERROR("%s: inode "DFID": cannot get layout, no LMV cached\n",
287                                sbi->ll_fsname, PFID(ll_inode2fid(inode)));
288                         GOTO(failed, rc = -EINVAL);
289                 }
290         } else {
291                 CERROR("%s: inode "DFID": not a regular file nor directory\n",
292                        sbi->ll_fsname, PFID(ll_inode2fid(inode)));
293                 GOTO(failed, rc = -EINVAL);
294         }
295
296         /* XXX no assert nor double check of magic, length and type ? */
297
298         rc = ll_foreign_symlink_parse(sbi, inode, lfm, &destname);
299
300 failed:
301         if (S_ISDIR(inode->i_mode))
302                 up_read(&lli->lli_lsm_sem);
303
304         if (S_ISREG(inode->i_mode) && lfm)
305                 OBD_FREE(lfm, lfm_size);
306
307         if (!rc) {
308                 *symname = destname;
309                 CDEBUG(D_INFO,
310                        "%s: inode "DFID": faking symlink to dest '%s'\n",
311                        sbi->ll_fsname, PFID(ll_inode2fid(inode)), destname);
312         }
313
314         RETURN(rc);
315 }
316
317 #ifdef HAVE_SYMLINK_OPS_USE_NAMEIDATA
318 static void ll_foreign_put_link(struct dentry *dentry,
319                         struct nameidata *nd, void *cookie)
320 #else
321 # ifdef HAVE_IOP_GET_LINK
322 static void ll_foreign_put_link(void *cookie)
323 # else
324 static void ll_foreign_put_link(struct inode *unused, void *cookie)
325 # endif
326 #endif
327 {
328         /* to avoid allocating an unnecessary big buffer, and since ways to
329          * build the symlink path from foreign LOV/LMV can be multiple and
330          * not constant. So it size is not known and we need to use
331          * strlen(cookie)+1 to determine its size and to avoid false positive
332          * to be reported by memory leak check code
333          */
334         OBD_FREE_LARGE(cookie, strlen(cookie) + 1);
335 }
336
337 #ifdef HAVE_SYMLINK_OPS_USE_NAMEIDATA
338 static void *ll_foreign_follow_link(struct dentry *dentry,
339                                       struct nameidata *nd)
340 {
341         struct inode *inode = dentry->d_inode;
342         int rc;
343         char *symname = NULL;
344
345         ENTRY;
346
347         CDEBUG(D_VFSTRACE, "VFS Op\n");
348         /*
349          * Limit the recursive symlink depth to 5 instead of default
350          * 8 links when kernel has 4k stack to prevent stack overflow.
351          * For 8k stacks we need to limit it to 7 for local servers.
352          */
353         if (THREAD_SIZE < 8192 && current->link_count >= 6)
354                 rc = -ELOOP;
355         else if (THREAD_SIZE == 8192 && current->link_count >= 8)
356                 rc = -ELOOP;
357         else
358                 rc = ll_foreign_readlink_internal(inode, &symname);
359
360         if (rc)
361                 symname = ERR_PTR(rc);
362
363         nd_set_link(nd, symname);
364         RETURN(symname);
365 }
366
367 #elif defined(HAVE_IOP_GET_LINK)
368 static const char *ll_foreign_get_link(struct dentry *dentry,
369                                        struct inode *inode,
370                                        struct delayed_call *done)
371 {
372         char *symname = NULL;
373         int rc;
374
375         ENTRY;
376         CDEBUG(D_VFSTRACE, "VFS Op\n");
377         if (!dentry)
378                 RETURN(ERR_PTR(-ECHILD));
379         rc = ll_foreign_readlink_internal(inode, &symname);
380
381         /*
382          * symname must be freed when we are done
383          *
384          * XXX we may avoid the need to do so if we use
385          * lli_symlink_name cache to retain symname and
386          * let ll_clear_inode free it...
387          */
388         set_delayed_call(done, ll_foreign_put_link, symname);
389         RETURN(rc ? ERR_PTR(rc) : symname);
390 }
391
392 # else /* !HAVE_IOP_GET_LINK */
393 static const char *ll_foreign_follow_link(struct dentry *dentry,
394                                             void **cookie)
395 {
396         struct inode *inode = d_inode(dentry);
397         char *symname = NULL;
398         int rc;
399
400         ENTRY;
401
402         CDEBUG(D_VFSTRACE, "VFS Op\n");
403         rc = ll_foreign_readlink_internal(inode, &symname);
404         if (rc < 0)
405                 return ERR_PTR(rc);
406
407         /* XXX need to also return symname in cookie in order to delay
408          * its release ??
409          */
410
411         RETURN(symname);
412 }
413
414 #endif /* HAVE_SYMLINK_OPS_USE_NAMEIDATA, HAVE_IOP_GET_LINK */
415
416 /*
417  * Should only be called for already in-use/cache foreign dir inode
418  * when foreign fake-symlink behaviour has been enabled afterward
419  */
420 static struct dentry *ll_foreign_dir_lookup(struct inode *parent,
421                                          struct dentry *dentry,
422                                          unsigned int flags)
423 {
424         CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s, dir="DFID"(%p)\n",
425                dentry->d_name.len, dentry->d_name.name,
426                PFID(ll_inode2fid(parent)), parent);
427
428         return ERR_PTR(-ENODATA);
429 }
430
431 static bool has_same_mount_namespace(struct ll_sb_info *sbi)
432 {
433         int rc;
434
435         rc = (sbi->ll_mnt.mnt == current->fs->root.mnt);
436         if (!rc)
437                 LCONSOLE_WARN("%s: client mount %s and '%s.%d' not in same mnt-namespace\n",
438                               sbi->ll_fsname, sbi->ll_kset.kobj.name,
439                               current->comm, current->pid);
440
441         return rc;
442 }
443
444 ssize_t foreign_symlink_enable_show(struct kobject *kobj,
445                                     struct attribute *attr, char *buf)
446 {
447         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
448                                               ll_kset.kobj);
449
450         return snprintf(buf, PAGE_SIZE, "%d\n",
451                         !!(sbi->ll_flags & LL_SBI_FOREIGN_SYMLINK));
452 }
453
454 /*
455  * XXX
456  * There should be already in-use/cached inodes of foreign files/dirs who
457  * will not-be/continue-to-be handled as fake-symlink, depending if
458  * feature is being enabled/disabled, until being revalidated.
459  * Also, does it require sbi->ll_lock protection ?
460  */
461 ssize_t foreign_symlink_enable_store(struct kobject *kobj,
462                                      struct attribute *attr,
463                                      const char *buffer, size_t count)
464 {
465         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
466                                               ll_kset.kobj);
467         unsigned int val;
468         int rc;
469
470         if (!has_same_mount_namespace(sbi))
471                 return -EINVAL;
472
473         rc = kstrtouint(buffer, 10, &val);
474         if (rc)
475                 return rc;
476
477         if (val)
478                 sbi->ll_flags |= LL_SBI_FOREIGN_SYMLINK;
479         else
480                 sbi->ll_flags &= ~LL_SBI_FOREIGN_SYMLINK;
481
482         return count;
483 }
484
485 ssize_t foreign_symlink_prefix_show(struct kobject *kobj,
486                                     struct attribute *attr, char *buf)
487 {
488         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
489                                               ll_kset.kobj);
490         ssize_t size;
491
492         down_read(&sbi->ll_foreign_symlink_sem);
493         size = snprintf(buf, PAGE_SIZE, "%s\n", sbi->ll_foreign_symlink_prefix);
494         up_read(&sbi->ll_foreign_symlink_sem);
495
496         return size;
497 }
498
499 ssize_t foreign_symlink_prefix_store(struct kobject *kobj,
500                                      struct attribute *attr,
501                                      const char *buffer, size_t count)
502 {
503         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
504                                               ll_kset.kobj);
505         char *new, *old;
506         size_t new_len, old_len;
507
508         if (!has_same_mount_namespace(sbi))
509                 return -EINVAL;
510
511         /* XXX strip buffer of any CR/LF,space,... ?? */
512
513         /* check buffer looks like a valid absolute path */
514         if (*buffer != '/') {
515                 CERROR("foreign symlink prefix must be an absolute path\n");
516                 return -EINVAL;
517         }
518         new_len = strnlen(buffer, count);
519         if (new_len < count)
520                 CDEBUG(D_INFO, "NUL byte found in %zu bytes\n", count);
521         if (new_len > PATH_MAX) {
522                 CERROR("%s: foreign symlink prefix length %zu > PATH_MAX\n",
523                        sbi->ll_fsname, new_len);
524                 return -EINVAL;
525         }
526         OBD_ALLOC(new, new_len + 1);
527         if (new == NULL) {
528                 CERROR("%s: can not allocate space for foreign path prefix\n",
529                        sbi->ll_fsname);
530                 return -ENOSPC;
531         }
532
533         down_write(&sbi->ll_foreign_symlink_sem);
534         old_len = sbi->ll_foreign_symlink_prefix_size;
535         old = sbi->ll_foreign_symlink_prefix;
536         memcpy(new, buffer, new_len);
537         *(new + new_len) = '\0';
538
539         sbi->ll_foreign_symlink_prefix = new;
540         sbi->ll_foreign_symlink_prefix_size = new_len + 1;
541         up_write(&sbi->ll_foreign_symlink_sem);
542
543         if (old)
544                 OBD_FREE(old, old_len);
545
546         return new_len;
547 }
548
549 ssize_t foreign_symlink_upcall_show(struct kobject *kobj,
550                                     struct attribute *attr, char *buf)
551 {
552         ssize_t size;
553         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
554                                               ll_kset.kobj);
555
556         down_read(&sbi->ll_foreign_symlink_sem);
557         size = snprintf(buf, PAGE_SIZE, "%s\n", sbi->ll_foreign_symlink_upcall);
558         up_read(&sbi->ll_foreign_symlink_sem);
559
560         return size;
561 }
562
563 ssize_t foreign_symlink_upcall_store(struct kobject *kobj,
564                                      struct attribute *attr,
565                                      const char *buffer, size_t count)
566 {
567         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
568                                               ll_kset.kobj);
569         char *old = NULL, *new = NULL;
570         size_t new_len;
571
572         if (!has_same_mount_namespace(sbi))
573                 return -EINVAL;
574
575         /* XXX strip buffer of any CR/LF,space,... ?? */
576
577         /* check buffer looks like a valid absolute path */
578         if (*buffer != '/' && strcmp(buffer, "none")) {
579                 CERROR("foreign symlink upcall must be an absolute path\n");
580                 return -EINVAL;
581         }
582         new_len = strnlen(buffer, count);
583         if (new_len < count)
584                 CDEBUG(D_INFO, "NULL byte found in %zu bytes\n", count);
585         if (new_len > PATH_MAX) {
586                 CERROR("%s: foreign symlink upcall path length %zu > PATH_MAX\n",
587                        sbi->ll_fsname, new_len);
588                 return -EINVAL;
589         }
590
591         OBD_ALLOC(new, new_len + 1);
592         if (new == NULL) {
593                 CERROR("%s: can not allocate space for foreign symlink upcall path\n",
594                        sbi->ll_fsname);
595                 return -ENOSPC;
596         }
597         memcpy(new, buffer, new_len);
598         *(new + new_len) = '\0';
599
600         down_write(&sbi->ll_foreign_symlink_sem);
601         old = sbi->ll_foreign_symlink_upcall;
602
603         sbi->ll_foreign_symlink_upcall = new;
604         /* LL_SBI_FOREIGN_SYMLINK_UPCALL will be set by
605          * foreign_symlink_upcall_info_store() upon valid being provided
606          * by upcall
607          * XXX there is a potential race if there are multiple concurent
608          * attempts to set upcall path and execution occur in different
609          * order, we may end up using the format provided by a different
610          * upcall than the one set in ll_foreign_symlink_upcall
611          */
612         sbi->ll_flags &= ~LL_SBI_FOREIGN_SYMLINK_UPCALL;
613         up_write(&sbi->ll_foreign_symlink_sem);
614
615         if (strcmp(new, "none")) {
616                 char *argv[] = {
617                           [0] = new,
618                           /* sbi sysfs object name */
619                           [1] = (char *)sbi->ll_kset.kobj.name,
620                           [2] = NULL
621                 };
622                 char *envp[] = {
623                           [0] = "HOME=/",
624                           [1] = "PATH=/sbin:/usr/sbin",
625                           [2] = NULL
626                 };
627                 int rc;
628
629                 rc = call_usermodehelper(new, argv, envp, UMH_WAIT_EXEC);
630                 if (rc < 0)
631                         CERROR("%s: error invoking foreign symlink upcall %s: rc %d\n",
632                                sbi->ll_fsname, new, rc);
633                 else
634                         CDEBUG(D_INFO, "%s: invoked upcall %s\n",
635                                sbi->ll_fsname, new);
636         }
637
638         if (old)
639                 OBD_FREE_LARGE(old, strlen(old) + 1);
640
641         return new_len;
642 }
643
644 /* foreign_symlink_upcall_info_store() stores format items in
645  * foreign_symlink_items[], and foreign_symlink_upcall_parse()
646  * uses it to parse each foreign symlink LOV/LMV EAs
647  */
648 ssize_t foreign_symlink_upcall_info_store(struct kobject *kobj,
649                                      struct attribute *attr,
650                                      const char *buffer, size_t count)
651 {
652         struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
653                                               ll_kset.kobj);
654         struct ll_foreign_symlink_upcall_item items[MAX_NB_UPCALL_ITEMS], *item;
655         struct ll_foreign_symlink_upcall_item *new_items, *old_items;
656         size_t remaining = count;
657         int nb_items = 0, old_nb_items, i, rc = 0;
658
659         ENTRY;
660
661         if (!has_same_mount_namespace(sbi))
662                 return -EINVAL;
663
664         /* parse buffer to check validity of infos and fill symlink format
665          * descriptors
666          */
667
668         if (count % sizeof(__u32) != 0) {
669                 CERROR("%s: invalid size '%zu' of infos buffer returned by foreign symlink upcall\n",
670                        sbi->ll_fsname, count);
671                 RETURN(-EINVAL);
672         }
673
674         /* evaluate number of items provided */
675         while (remaining > 0) {
676                 item = (struct ll_foreign_symlink_upcall_item *)
677                                 &buffer[count - remaining];
678                 switch (item->type) {
679                 case STRING_TYPE: {
680                         /* a constant string following */
681                         if (item->size >= remaining -
682                             offsetof(struct ll_foreign_symlink_upcall_item,
683                                      bytestring) - sizeof(item->type)) {
684                                 /* size of string must not overflow remaining
685                                  * bytes minus EOB_TYPE item
686                                  */
687                                 CERROR("%s: constant string too long in infos buffer returned by foreign symlink upcall\n",
688                                        sbi->ll_fsname);
689                                 GOTO(failed, rc = -EINVAL);
690                         }
691                         OBD_ALLOC(items[nb_items].string,
692                                   item->size);
693                         if (items[nb_items].string == NULL) {
694                                 CERROR("%s: constant string allocation has failed for constant string of size %zu\n",
695                                        sbi->ll_fsname, item->size);
696                                 GOTO(failed, rc = -ENOMEM);
697                         }
698                         memcpy(items[nb_items].string,
699                                item->bytestring, item->size);
700                         items[nb_items].size = item->size;
701                         /* string items to fit on __u32 boundary */
702                         remaining = remaining - STRING_ITEM_SZ(item->size);
703                         break;
704                 }
705                 case POSLEN_TYPE: {
706                         /* a tuple (pos,len) following to delimit a sub-string
707                          * in lfm_value
708                          */
709                         items[nb_items].pos = item->pos;
710                         items[nb_items].len = item->len;
711                         remaining -= POSLEN_ITEM_SZ;
712                         break;
713                 }
714                 case EOB_TYPE:
715                         if (remaining != sizeof(item->type)) {
716                                 CERROR("%s: early end of infos buffer returned by foreign symlink upcall\n",
717                                        sbi->ll_fsname);
718                                 GOTO(failed, rc = -EINVAL);
719                         }
720                         remaining -= sizeof(item->type);
721                         break;
722                 default:
723                         CERROR("%s: wrong type '%u' encountered at pos %zu , with %zu remaining bytes, in infos buffer returned by foreign symlink upcall\n",
724                                sbi->ll_fsname, (__u32)buffer[count - remaining],
725                                count - remaining, remaining);
726                         GOTO(failed, rc = -EINVAL);
727                 }
728
729                 items[nb_items].type = item->type;
730                 nb_items++;
731                 if (nb_items >= MAX_NB_UPCALL_ITEMS) {
732                         CERROR("%s: too many items in infos buffer returned by foreign symlink upcall\n",
733                                sbi->ll_fsname);
734                         GOTO(failed, rc = -EINVAL);
735                 }
736         }
737         /* valid format has been provided by foreign symlink user upcall */
738         OBD_ALLOC_LARGE(new_items, nb_items *
739                         sizeof(struct ll_foreign_symlink_upcall_item));
740         if (new_items == NULL) {
741                 CERROR("%s: constant string allocation has failed for constant string of size %zu\n",
742                        sbi->ll_fsname, nb_items *
743                         sizeof(struct ll_foreign_symlink_upcall_item));
744                 GOTO(failed, rc = -ENOMEM);
745         }
746         for (i = 0; i < nb_items; i++)
747                 *((struct ll_foreign_symlink_upcall_item *)new_items + i) =
748                         items[i];
749
750         down_write(&sbi->ll_foreign_symlink_sem);
751         old_items = sbi->ll_foreign_symlink_upcall_items;
752         old_nb_items = sbi->ll_foreign_symlink_upcall_nb_items;
753         sbi->ll_foreign_symlink_upcall_items = new_items;
754         sbi->ll_foreign_symlink_upcall_nb_items = nb_items;
755         sbi->ll_flags |= LL_SBI_FOREIGN_SYMLINK_UPCALL;
756         up_write(&sbi->ll_foreign_symlink_sem);
757
758         /* free old_items */
759         if (old_items != NULL) {
760                 for (i = 0 ; i < old_nb_items; i++)
761                         if (old_items[i].type == STRING_TYPE)
762                                 OBD_FREE(old_items[i].string,
763                                          old_items[i].size);
764
765                 OBD_FREE_LARGE(old_items, old_nb_items *
766                                sizeof(struct ll_foreign_symlink_upcall_item));
767         }
768
769 failed:
770         /* clean items[] and free any strings */
771         if (rc != 0) {
772                 for (i = 0; i < nb_items; i++) {
773                         switch (items[i].type) {
774                         case STRING_TYPE:
775                                 OBD_FREE(items[i].string, items[i].size);
776                                 items[i].string = NULL;
777                                 items[i].size = 0;
778                                 break;
779                         case POSLEN_TYPE:
780                                 items[i].pos = 0;
781                                 items[i].len = 0;
782                                 break;
783                         case EOB_TYPE:
784                                 break;
785                         default:
786                                 CERROR("%s: wrong '%u'type encountered in foreign symlink upcall items\n",
787                                        sbi->ll_fsname, items[i].type);
788                                 GOTO(failed, rc = -EINVAL);
789                                 break;
790                         }
791                         items[i].type = 0;
792                 }
793         }
794
795         RETURN(rc == 0 ? count : rc);
796 }
797
798 struct inode_operations ll_foreign_file_symlink_inode_operations = {
799 #ifdef HAVE_IOP_GENERIC_READLINK
800         .readlink       = generic_readlink,
801 #endif
802         .setattr        = ll_setattr,
803 #ifdef HAVE_IOP_GET_LINK
804         .get_link       = ll_foreign_get_link,
805 #else
806         .follow_link    = ll_foreign_follow_link,
807         /* .put_link method required since need to release symlink copy buf */
808         .put_link       = ll_foreign_put_link,
809 #endif
810         .getattr        = ll_foreign_symlink_getattr,
811         .permission     = ll_inode_permission,
812 #ifdef HAVE_IOP_XATTR
813         .setxattr       = ll_setxattr,
814         .getxattr       = ll_getxattr,
815         .removexattr    = ll_removexattr,
816 #endif
817         .listxattr      = ll_listxattr,
818 };
819
820 struct inode_operations ll_foreign_dir_symlink_inode_operations = {
821         .lookup         = ll_foreign_dir_lookup,
822 #ifdef HAVE_IOP_GENERIC_READLINK
823         .readlink       = generic_readlink,
824 #endif
825         .setattr        = ll_setattr,
826 #ifdef HAVE_IOP_GET_LINK
827         .get_link       = ll_foreign_get_link,
828 #else
829         .follow_link    = ll_foreign_follow_link,
830         .put_link       = ll_foreign_put_link,
831 #endif
832         .getattr        = ll_foreign_symlink_getattr,
833         .permission     = ll_inode_permission,
834 #ifdef HAVE_IOP_XATTR
835         .setxattr       = ll_setxattr,
836         .getxattr       = ll_getxattr,
837         .removexattr    = ll_removexattr,
838 #endif
839         .listxattr      = ll_listxattr,
840 };
841
842 /* foreign fake-symlink version of ll_getattr() */
843 #ifdef HAVE_INODEOPS_ENHANCED_GETATTR
844 int ll_foreign_symlink_getattr(const struct path *path, struct kstat *stat,
845                                u32 request_mask, unsigned int flags)
846 {
847         return ll_getattr_dentry(path->dentry, stat, request_mask, flags,
848                                  true);
849 }
850 #else
851 int ll_foreign_symlink_getattr(struct vfsmount *mnt, struct dentry *de,
852                                struct kstat *stat)
853 {
854         return ll_getattr_dentry(de, stat, STATX_BASIC_STATS,
855                                  AT_STATX_SYNC_AS_STAT, true);
856 }
857 #endif