orangefs: rename orangefs_inode_getattr to orangefs_inode_old_getattr
[linux-2.6-block.git] / fs / orangefs / orangefs-utils.c
1 /*
2  * (C) 2001 Clemson University and The University of Chicago
3  *
4  * See COPYING in top-level directory.
5  */
6 #include "protocol.h"
7 #include "orangefs-kernel.h"
8 #include "orangefs-dev-proto.h"
9 #include "orangefs-bufmap.h"
10
11 __s32 fsid_of_op(struct orangefs_kernel_op_s *op)
12 {
13         __s32 fsid = ORANGEFS_FS_ID_NULL;
14
15         if (op) {
16                 switch (op->upcall.type) {
17                 case ORANGEFS_VFS_OP_FILE_IO:
18                         fsid = op->upcall.req.io.refn.fs_id;
19                         break;
20                 case ORANGEFS_VFS_OP_LOOKUP:
21                         fsid = op->upcall.req.lookup.parent_refn.fs_id;
22                         break;
23                 case ORANGEFS_VFS_OP_CREATE:
24                         fsid = op->upcall.req.create.parent_refn.fs_id;
25                         break;
26                 case ORANGEFS_VFS_OP_GETATTR:
27                         fsid = op->upcall.req.getattr.refn.fs_id;
28                         break;
29                 case ORANGEFS_VFS_OP_REMOVE:
30                         fsid = op->upcall.req.remove.parent_refn.fs_id;
31                         break;
32                 case ORANGEFS_VFS_OP_MKDIR:
33                         fsid = op->upcall.req.mkdir.parent_refn.fs_id;
34                         break;
35                 case ORANGEFS_VFS_OP_READDIR:
36                         fsid = op->upcall.req.readdir.refn.fs_id;
37                         break;
38                 case ORANGEFS_VFS_OP_SETATTR:
39                         fsid = op->upcall.req.setattr.refn.fs_id;
40                         break;
41                 case ORANGEFS_VFS_OP_SYMLINK:
42                         fsid = op->upcall.req.sym.parent_refn.fs_id;
43                         break;
44                 case ORANGEFS_VFS_OP_RENAME:
45                         fsid = op->upcall.req.rename.old_parent_refn.fs_id;
46                         break;
47                 case ORANGEFS_VFS_OP_STATFS:
48                         fsid = op->upcall.req.statfs.fs_id;
49                         break;
50                 case ORANGEFS_VFS_OP_TRUNCATE:
51                         fsid = op->upcall.req.truncate.refn.fs_id;
52                         break;
53                 case ORANGEFS_VFS_OP_MMAP_RA_FLUSH:
54                         fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
55                         break;
56                 case ORANGEFS_VFS_OP_FS_UMOUNT:
57                         fsid = op->upcall.req.fs_umount.fs_id;
58                         break;
59                 case ORANGEFS_VFS_OP_GETXATTR:
60                         fsid = op->upcall.req.getxattr.refn.fs_id;
61                         break;
62                 case ORANGEFS_VFS_OP_SETXATTR:
63                         fsid = op->upcall.req.setxattr.refn.fs_id;
64                         break;
65                 case ORANGEFS_VFS_OP_LISTXATTR:
66                         fsid = op->upcall.req.listxattr.refn.fs_id;
67                         break;
68                 case ORANGEFS_VFS_OP_REMOVEXATTR:
69                         fsid = op->upcall.req.removexattr.refn.fs_id;
70                         break;
71                 case ORANGEFS_VFS_OP_FSYNC:
72                         fsid = op->upcall.req.fsync.refn.fs_id;
73                         break;
74                 default:
75                         break;
76                 }
77         }
78         return fsid;
79 }
80
81 static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
82 {
83         int flags = 0;
84         if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
85                 flags |= S_IMMUTABLE;
86         else
87                 flags &= ~S_IMMUTABLE;
88         if (attrs->flags & ORANGEFS_APPEND_FL)
89                 flags |= S_APPEND;
90         else
91                 flags &= ~S_APPEND;
92         if (attrs->flags & ORANGEFS_NOATIME_FL)
93                 flags |= S_NOATIME;
94         else
95                 flags &= ~S_NOATIME;
96         return flags;
97 }
98
99 static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
100 {
101         int perm_mode = 0;
102
103         if (attrs->perms & ORANGEFS_O_EXECUTE)
104                 perm_mode |= S_IXOTH;
105         if (attrs->perms & ORANGEFS_O_WRITE)
106                 perm_mode |= S_IWOTH;
107         if (attrs->perms & ORANGEFS_O_READ)
108                 perm_mode |= S_IROTH;
109
110         if (attrs->perms & ORANGEFS_G_EXECUTE)
111                 perm_mode |= S_IXGRP;
112         if (attrs->perms & ORANGEFS_G_WRITE)
113                 perm_mode |= S_IWGRP;
114         if (attrs->perms & ORANGEFS_G_READ)
115                 perm_mode |= S_IRGRP;
116
117         if (attrs->perms & ORANGEFS_U_EXECUTE)
118                 perm_mode |= S_IXUSR;
119         if (attrs->perms & ORANGEFS_U_WRITE)
120                 perm_mode |= S_IWUSR;
121         if (attrs->perms & ORANGEFS_U_READ)
122                 perm_mode |= S_IRUSR;
123
124         if (attrs->perms & ORANGEFS_G_SGID)
125                 perm_mode |= S_ISGID;
126         if (attrs->perms & ORANGEFS_U_SUID)
127                 perm_mode |= S_ISUID;
128
129         return perm_mode;
130 }
131
132 /* NOTE: symname is ignored unless the inode is a sym link */
133 static int copy_attributes_to_inode(struct inode *inode,
134                                     struct ORANGEFS_sys_attr_s *attrs,
135                                     char *symname)
136 {
137         int ret = -1;
138         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
139         loff_t inode_size = 0;
140         loff_t rounded_up_size = 0;
141
142
143         /*
144          * arbitrarily set the inode block size; FIXME: we need to
145          * resolve the difference between the reported inode blocksize
146          * and the PAGE_CACHE_SIZE, since our block count will always
147          * be wrong.
148          *
149          * For now, we're setting the block count to be the proper
150          * number assuming the block size is 512 bytes, and the size is
151          * rounded up to the nearest 4K.  This is apparently required
152          * to get proper size reports from the 'du' shell utility.
153          *
154          * changing the inode->i_blkbits to something other than
155          * PAGE_CACHE_SHIFT breaks mmap/execution as we depend on that.
156          */
157         gossip_debug(GOSSIP_UTILS_DEBUG,
158                      "attrs->mask = %x (objtype = %s)\n",
159                      attrs->mask,
160                      attrs->objtype == ORANGEFS_TYPE_METAFILE ? "file" :
161                      attrs->objtype == ORANGEFS_TYPE_DIRECTORY ? "directory" :
162                      attrs->objtype == ORANGEFS_TYPE_SYMLINK ? "symlink" :
163                         "invalid/unknown");
164
165         switch (attrs->objtype) {
166         case ORANGEFS_TYPE_METAFILE:
167                 inode->i_flags = orangefs_inode_flags(attrs);
168                 if (attrs->mask & ORANGEFS_ATTR_SYS_SIZE) {
169                         inode_size = (loff_t) attrs->size;
170                         rounded_up_size =
171                             (inode_size + (4096 - (inode_size % 4096)));
172
173                         spin_lock(&inode->i_lock);
174                         inode->i_bytes = inode_size;
175                         inode->i_blocks =
176                             (unsigned long)(rounded_up_size / 512);
177                         spin_unlock(&inode->i_lock);
178
179                         /*
180                          * NOTE: make sure all the places we're called
181                          * from have the inode->i_sem lock. We're fine
182                          * in 99% of the cases since we're mostly
183                          * called from a lookup.
184                          */
185                         inode->i_size = inode_size;
186                 }
187                 break;
188         case ORANGEFS_TYPE_SYMLINK:
189                 if (symname != NULL) {
190                         inode->i_size = (loff_t) strlen(symname);
191                         break;
192                 }
193                 /*FALLTHRU*/
194         default:
195                 inode->i_size = PAGE_CACHE_SIZE;
196
197                 spin_lock(&inode->i_lock);
198                 inode_set_bytes(inode, inode->i_size);
199                 spin_unlock(&inode->i_lock);
200                 break;
201         }
202
203         inode->i_uid = make_kuid(&init_user_ns, attrs->owner);
204         inode->i_gid = make_kgid(&init_user_ns, attrs->group);
205         inode->i_atime.tv_sec = (time64_t) attrs->atime;
206         inode->i_mtime.tv_sec = (time64_t) attrs->mtime;
207         inode->i_ctime.tv_sec = (time64_t) attrs->ctime;
208         inode->i_atime.tv_nsec = 0;
209         inode->i_mtime.tv_nsec = 0;
210         inode->i_ctime.tv_nsec = 0;
211
212         inode->i_mode = orangefs_inode_perms(attrs);
213
214         if (is_root_handle(inode)) {
215                 /* special case: mark the root inode as sticky */
216                 inode->i_mode |= S_ISVTX;
217                 gossip_debug(GOSSIP_UTILS_DEBUG,
218                              "Marking inode %pU as sticky\n",
219                              get_khandle_from_ino(inode));
220         }
221
222         switch (attrs->objtype) {
223         case ORANGEFS_TYPE_METAFILE:
224                 inode->i_mode |= S_IFREG;
225                 ret = 0;
226                 break;
227         case ORANGEFS_TYPE_DIRECTORY:
228                 inode->i_mode |= S_IFDIR;
229                 /* NOTE: we have no good way to keep nlink consistent
230                  * for directories across clients; keep constant at 1.
231                  * Why 1?  If we go with 2, then find(1) gets confused
232                  * and won't work properly withouth the -noleaf option
233                  */
234                 set_nlink(inode, 1);
235                 ret = 0;
236                 break;
237         case ORANGEFS_TYPE_SYMLINK:
238                 inode->i_mode |= S_IFLNK;
239
240                 /* copy link target to inode private data */
241                 if (orangefs_inode && symname) {
242                         strncpy(orangefs_inode->link_target,
243                                 symname,
244                                 ORANGEFS_NAME_MAX);
245                         gossip_debug(GOSSIP_UTILS_DEBUG,
246                                      "Copied attr link target %s\n",
247                                      orangefs_inode->link_target);
248                 }
249                 gossip_debug(GOSSIP_UTILS_DEBUG,
250                              "symlink mode %o\n",
251                              inode->i_mode);
252                 ret = 0;
253                 break;
254         default:
255                 gossip_err("orangefs: copy_attributes_to_inode: got invalid attribute type %x\n",
256                         attrs->objtype);
257         }
258
259         gossip_debug(GOSSIP_UTILS_DEBUG,
260                      "orangefs: copy_attributes_to_inode: setting i_mode to %o, i_size to %lu\n",
261                      inode->i_mode,
262                      (unsigned long)i_size_read(inode));
263
264         return ret;
265 }
266
267 /*
268  * NOTE: in kernel land, we never use the sys_attr->link_target for
269  * anything, so don't bother copying it into the sys_attr object here.
270  */
271 static inline int copy_attributes_from_inode(struct inode *inode,
272                                              struct ORANGEFS_sys_attr_s *attrs,
273                                              struct iattr *iattr)
274 {
275         umode_t tmp_mode;
276
277         if (!iattr || !inode || !attrs) {
278                 gossip_err("NULL iattr (%p), inode (%p), attrs (%p) "
279                            "in copy_attributes_from_inode!\n",
280                            iattr,
281                            inode,
282                            attrs);
283                 return -EINVAL;
284         }
285         /*
286          * We need to be careful to only copy the attributes out of the
287          * iattr object that we know are valid.
288          */
289         attrs->mask = 0;
290         if (iattr->ia_valid & ATTR_UID) {
291                 attrs->owner = from_kuid(current_user_ns(), iattr->ia_uid);
292                 attrs->mask |= ORANGEFS_ATTR_SYS_UID;
293                 gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
294         }
295         if (iattr->ia_valid & ATTR_GID) {
296                 attrs->group = from_kgid(current_user_ns(), iattr->ia_gid);
297                 attrs->mask |= ORANGEFS_ATTR_SYS_GID;
298                 gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
299         }
300
301         if (iattr->ia_valid & ATTR_ATIME) {
302                 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
303                 if (iattr->ia_valid & ATTR_ATIME_SET) {
304                         attrs->atime = (time64_t)iattr->ia_atime.tv_sec;
305                         attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
306                 }
307         }
308         if (iattr->ia_valid & ATTR_MTIME) {
309                 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
310                 if (iattr->ia_valid & ATTR_MTIME_SET) {
311                         attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec;
312                         attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
313                 }
314         }
315         if (iattr->ia_valid & ATTR_CTIME)
316                 attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
317
318         /*
319          * ORANGEFS cannot set size with a setattr operation.  Probably not likely
320          * to be requested through the VFS, but just in case, don't worry about
321          * ATTR_SIZE
322          */
323
324         if (iattr->ia_valid & ATTR_MODE) {
325                 tmp_mode = iattr->ia_mode;
326                 if (tmp_mode & (S_ISVTX)) {
327                         if (is_root_handle(inode)) {
328                                 /*
329                                  * allow sticky bit to be set on root (since
330                                  * it shows up that way by default anyhow),
331                                  * but don't show it to the server
332                                  */
333                                 tmp_mode -= S_ISVTX;
334                         } else {
335                                 gossip_debug(GOSSIP_UTILS_DEBUG,
336                                              "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
337                                 return -EINVAL;
338                         }
339                 }
340
341                 if (tmp_mode & (S_ISUID)) {
342                         gossip_debug(GOSSIP_UTILS_DEBUG,
343                                      "Attempting to set setuid bit (not supported); returning EINVAL.\n");
344                         return -EINVAL;
345                 }
346
347                 attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
348                 attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
349         }
350
351         return 0;
352 }
353
354 static int compare_attributes_to_inode(struct inode *inode,
355                                        struct ORANGEFS_sys_attr_s *attrs,
356                                        char *symname,
357                                        int mask)
358 {
359         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
360         loff_t inode_size, rounded_up_size;
361
362         /* Much of what happens below relies on the type being around. */
363         if (!(mask & ORANGEFS_ATTR_SYS_TYPE))
364                 return 0;
365
366         if (attrs->objtype == ORANGEFS_TYPE_METAFILE &&
367             inode->i_flags != orangefs_inode_flags(attrs))
368                 return 0;
369
370         /* Compare file size. */
371
372         switch (attrs->objtype) {
373         case ORANGEFS_TYPE_METAFILE:
374                 if (mask & ORANGEFS_ATTR_SYS_SIZE) {
375                         inode_size = attrs->size;
376                         rounded_up_size = inode_size +
377                             (4096 - (inode_size % 4096));
378                         if (inode->i_bytes != inode_size ||
379                             inode->i_blocks != rounded_up_size/512)
380                                 return 0;
381                 }
382                 break;
383         case ORANGEFS_TYPE_SYMLINK:
384                 if (mask & ORANGEFS_ATTR_SYS_SIZE)
385                         if (symname && strlen(symname) != inode->i_size)
386                                 return 0;
387                 break;
388         default:
389                 if (inode->i_size != PAGE_CACHE_SIZE &&
390                     inode_get_bytes(inode) != PAGE_CACHE_SIZE)
391                         return 0;
392         }
393
394         /* Compare general attributes. */
395
396         if (mask & ORANGEFS_ATTR_SYS_UID &&
397             !uid_eq(inode->i_uid, make_kuid(&init_user_ns, attrs->owner)))
398                 return 0;
399         if (mask & ORANGEFS_ATTR_SYS_GID &&
400             !gid_eq(inode->i_gid, make_kgid(&init_user_ns, attrs->group)))
401                 return 0;
402         if (mask & ORANGEFS_ATTR_SYS_ATIME &&
403             inode->i_atime.tv_sec != attrs->atime)
404                 return 0;
405         if (mask & ORANGEFS_ATTR_SYS_MTIME &&
406             inode->i_atime.tv_sec != attrs->mtime)
407                 return 0;
408         if (mask & ORANGEFS_ATTR_SYS_CTIME &&
409             inode->i_atime.tv_sec != attrs->ctime)
410                 return 0;
411         if (inode->i_atime.tv_nsec != 0 ||
412             inode->i_mtime.tv_nsec != 0 ||
413             inode->i_ctime.tv_nsec != 0)
414                 return 0;
415
416         if (mask & ORANGEFS_ATTR_SYS_PERM &&
417             (inode->i_mode & ~(S_ISVTX|S_IFREG|S_IFDIR|S_IFLNK)) !=
418             orangefs_inode_perms(attrs))
419                 return 0;
420
421         if (is_root_handle(inode))
422                 if (!(inode->i_mode & S_ISVTX))
423                         return 0;
424
425         /* Compare file type. */
426
427         switch (attrs->objtype) {
428         case ORANGEFS_TYPE_METAFILE:
429                 if (!S_ISREG(inode->i_mode))
430                         return 0;
431                 break;
432         case ORANGEFS_TYPE_DIRECTORY:
433                 if (!S_ISDIR(inode->i_mode))
434                         return 0;
435                 if (inode->i_nlink != 1)
436                         return 0;
437                 break;
438         case ORANGEFS_TYPE_SYMLINK:
439                 if (!S_ISLNK(inode->i_mode))
440                         return 0;
441                 if (orangefs_inode && symname &&
442                     mask & ORANGEFS_ATTR_SYS_LNK_TARGET)
443                         if (strcmp(orangefs_inode->link_target, symname))
444                                 return 0;
445                 break;
446         default:
447                 gossip_err("orangefs: compare_attributes_to_inode: got invalid attribute type %x\n",
448                     attrs->objtype);
449
450         }
451
452         return 1;
453 }
454
455 /*
456  * Issues a orangefs getattr request and fills in the appropriate inode
457  * attributes if successful. When check is 0, returns 0 on success and -errno
458  * otherwise. When check is 1, returns 1 on success where the inode is valid
459  * and 0 on success where the inode is stale and -errno otherwise.
460  */
461 int orangefs_inode_old_getattr(struct inode *inode, __u32 getattr_mask,
462     int check)
463 {
464         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
465         struct orangefs_kernel_op_s *new_op;
466         int ret = -EINVAL;
467
468         gossip_debug(GOSSIP_UTILS_DEBUG,
469                      "%s: called on inode %pU\n",
470                      __func__,
471                      get_khandle_from_ino(inode));
472
473         new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
474         if (!new_op)
475                 return -ENOMEM;
476         new_op->upcall.req.getattr.refn = orangefs_inode->refn;
477         new_op->upcall.req.getattr.mask = getattr_mask;
478
479         ret = service_operation(new_op, __func__,
480                                 get_interruptible_flag(inode));
481         if (ret != 0)
482                 goto out;
483
484         if (check) {
485                 ret = compare_attributes_to_inode(inode,
486                     &new_op->downcall.resp.getattr.attributes,
487                     new_op->downcall.resp.getattr.link_target,
488                     getattr_mask);
489
490                 if (new_op->downcall.resp.getattr.attributes.objtype ==
491                     ORANGEFS_TYPE_METAFILE) {
492                         if (orangefs_inode->blksize !=
493                             new_op->downcall.resp.getattr.attributes.blksize)
494                                 ret = 0;
495                 } else {
496                         if (orangefs_inode->blksize != 1 << inode->i_blkbits)
497                                 ret = 0;
498                 }
499         } else {
500                 if (copy_attributes_to_inode(inode,
501                                 &new_op->downcall.resp.getattr.attributes,
502                                 new_op->downcall.resp.getattr.link_target)) {
503                         gossip_err("%s: failed to copy attributes\n", __func__);
504                         ret = -ENOENT;
505                         goto out;
506                 }
507
508                 /*
509                  * Store blksize in orangefs specific part of inode structure;
510                  * we are only going to use this to report to stat to make sure
511                  * it doesn't perturb any inode related code paths.
512                  */
513                 if (new_op->downcall.resp.getattr.attributes.objtype ==
514                                 ORANGEFS_TYPE_METAFILE) {
515                         orangefs_inode->blksize = new_op->downcall.resp.
516                             getattr.attributes.blksize;
517                 } else {
518                         /*
519                          * mimic behavior of generic_fillattr() for other file
520                          * types.
521                          */
522                         orangefs_inode->blksize = (1 << inode->i_blkbits);
523
524                 }
525         }
526
527 out:
528         gossip_debug(GOSSIP_UTILS_DEBUG,
529                      "Getattr on handle %pU, "
530                      "fsid %d\n  (inode ct = %d) returned %d\n",
531                      &orangefs_inode->refn.khandle,
532                      orangefs_inode->refn.fs_id,
533                      (int)atomic_read(&inode->i_count),
534                      ret);
535
536         op_release(new_op);
537         return ret;
538 }
539
540 static int orangefs_inode_type(enum orangefs_ds_type objtype)
541 {
542         if (objtype == ORANGEFS_TYPE_METAFILE)
543                 return S_IFREG;
544         else if (objtype == ORANGEFS_TYPE_DIRECTORY)
545                 return S_IFDIR;
546         else if (objtype == ORANGEFS_TYPE_SYMLINK)
547                 return S_IFLNK;
548         else
549                 return -1;
550 }
551
552 int orangefs_inode_getattr(struct inode *inode, int new, int size)
553 {
554         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
555         struct orangefs_kernel_op_s *new_op;
556         loff_t inode_size, rounded_up_size;
557         int ret;
558
559         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
560             get_khandle_from_ino(inode));
561
562         new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
563         if (!new_op)
564                 return -ENOMEM;
565         new_op->upcall.req.getattr.refn = orangefs_inode->refn;
566         new_op->upcall.req.getattr.mask = size ?
567             ORANGEFS_ATTR_SYS_ALL_NOHINT : ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE;
568
569         ret = service_operation(new_op, __func__,
570             get_interruptible_flag(inode));
571         if (ret != 0)
572                 goto out;
573
574         ret = orangefs_inode_type(new_op->
575             downcall.resp.getattr.attributes.objtype);
576         if (!new) {
577                 /*
578                  * If the inode type or symlink target have changed then this
579                  * inode is stale.
580                  */
581                 if (ret == -1 || !(inode->i_mode & ret)) {
582                         orangefs_make_bad_inode(inode);
583                         ret = -ESTALE;
584                         goto out;
585                 }
586                 if (ret == S_IFLNK && strncmp(orangefs_inode->link_target,
587                     new_op->downcall.resp.getattr.link_target,
588                     ORANGEFS_NAME_MAX)) {
589                         orangefs_make_bad_inode(inode);
590                         ret = -ESTALE;
591                         goto out;
592                 }
593         }
594
595         switch (ret) {
596         case S_IFREG:
597                 inode->i_flags = orangefs_inode_flags(&new_op->
598                     downcall.resp.getattr.attributes);
599                 if (size) {
600                         inode_size = (loff_t)new_op->
601                             downcall.resp.getattr.attributes.size;
602                         rounded_up_size =
603                             (inode_size + (4096 - (inode_size % 4096)));
604                         inode->i_size = inode_size;
605                         orangefs_inode->blksize =
606                             new_op->downcall.resp.getattr.attributes.blksize;
607                         spin_lock(&inode->i_lock);
608                         inode->i_bytes = inode_size;
609                         inode->i_blocks =
610                             (unsigned long)(rounded_up_size / 512);
611                         spin_unlock(&inode->i_lock);
612                 }
613                 break;
614         case S_IFDIR:
615                 inode->i_size = PAGE_CACHE_SIZE;
616                 orangefs_inode->blksize = (1 << inode->i_blkbits);
617                 spin_lock(&inode->i_lock);
618                 inode_set_bytes(inode, inode->i_size);
619                 spin_unlock(&inode->i_lock);
620                 set_nlink(inode, 1);
621                 break;
622         case S_IFLNK:
623                 if (new) {
624                         inode->i_size = (loff_t)strlen(new_op->
625                             downcall.resp.getattr.link_target);
626                         orangefs_inode->blksize = (1 << inode->i_blkbits);
627                         strlcpy(orangefs_inode->link_target,
628                             new_op->downcall.resp.getattr.link_target,
629                             ORANGEFS_NAME_MAX);
630                 }
631                 break;
632         }
633
634         inode->i_uid = make_kuid(&init_user_ns, new_op->
635             downcall.resp.getattr.attributes.owner);
636         inode->i_gid = make_kgid(&init_user_ns, new_op->
637             downcall.resp.getattr.attributes.group);
638         inode->i_atime.tv_sec = (time64_t)new_op->
639             downcall.resp.getattr.attributes.atime;
640         inode->i_mtime.tv_sec = (time64_t)new_op->
641             downcall.resp.getattr.attributes.mtime;
642         inode->i_ctime.tv_sec = (time64_t)new_op->
643             downcall.resp.getattr.attributes.ctime;
644         inode->i_atime.tv_nsec = 0;
645         inode->i_mtime.tv_nsec = 0;
646         inode->i_ctime.tv_nsec = 0;
647
648         /* special case: mark the root inode as sticky */
649         inode->i_mode = ret | (is_root_handle(inode) ? S_ISVTX : 0) |
650             orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
651
652         ret = 0;
653 out:
654         op_release(new_op);
655         return ret;
656 }
657
658 /*
659  * issues a orangefs setattr request to make sure the new attribute values
660  * take effect if successful.  returns 0 on success; -errno otherwise
661  */
662 int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
663 {
664         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
665         struct orangefs_kernel_op_s *new_op;
666         int ret;
667
668         new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
669         if (!new_op)
670                 return -ENOMEM;
671
672         new_op->upcall.req.setattr.refn = orangefs_inode->refn;
673         ret = copy_attributes_from_inode(inode,
674                        &new_op->upcall.req.setattr.attributes,
675                        iattr);
676         if (ret >= 0) {
677                 ret = service_operation(new_op, __func__,
678                                 get_interruptible_flag(inode));
679
680                 gossip_debug(GOSSIP_UTILS_DEBUG,
681                              "orangefs_inode_setattr: returning %d\n",
682                              ret);
683         }
684
685         op_release(new_op);
686
687         /*
688          * successful setattr should clear the atime, mtime and
689          * ctime flags.
690          */
691         if (ret == 0) {
692                 ClearAtimeFlag(orangefs_inode);
693                 ClearMtimeFlag(orangefs_inode);
694                 ClearCtimeFlag(orangefs_inode);
695                 ClearModeFlag(orangefs_inode);
696         }
697
698         return ret;
699 }
700
701 int orangefs_flush_inode(struct inode *inode)
702 {
703         /*
704          * If it is a dirty inode, this function gets called.
705          * Gather all the information that needs to be setattr'ed
706          * Right now, this will only be used for mode, atime, mtime
707          * and/or ctime.
708          */
709         struct iattr wbattr;
710         int ret;
711         int mtime_flag;
712         int ctime_flag;
713         int atime_flag;
714         int mode_flag;
715         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
716
717         memset(&wbattr, 0, sizeof(wbattr));
718
719         /*
720          * check inode flags up front, and clear them if they are set.  This
721          * will prevent multiple processes from all trying to flush the same
722          * inode if they call close() simultaneously
723          */
724         mtime_flag = MtimeFlag(orangefs_inode);
725         ClearMtimeFlag(orangefs_inode);
726         ctime_flag = CtimeFlag(orangefs_inode);
727         ClearCtimeFlag(orangefs_inode);
728         atime_flag = AtimeFlag(orangefs_inode);
729         ClearAtimeFlag(orangefs_inode);
730         mode_flag = ModeFlag(orangefs_inode);
731         ClearModeFlag(orangefs_inode);
732
733         /*  -- Lazy atime,mtime and ctime update --
734          * Note: all times are dictated by server in the new scheme
735          * and not by the clients
736          *
737          * Also mode updates are being handled now..
738          */
739
740         if (mtime_flag)
741                 wbattr.ia_valid |= ATTR_MTIME;
742         if (ctime_flag)
743                 wbattr.ia_valid |= ATTR_CTIME;
744         if (atime_flag)
745                 wbattr.ia_valid |= ATTR_ATIME;
746
747         if (mode_flag) {
748                 wbattr.ia_mode = inode->i_mode;
749                 wbattr.ia_valid |= ATTR_MODE;
750         }
751
752         gossip_debug(GOSSIP_UTILS_DEBUG,
753                      "*********** orangefs_flush_inode: %pU "
754                      "(ia_valid %d)\n",
755                      get_khandle_from_ino(inode),
756                      wbattr.ia_valid);
757         if (wbattr.ia_valid == 0) {
758                 gossip_debug(GOSSIP_UTILS_DEBUG,
759                              "orangefs_flush_inode skipping setattr()\n");
760                 return 0;
761         }
762
763         gossip_debug(GOSSIP_UTILS_DEBUG,
764                      "orangefs_flush_inode (%pU) writing mode %o\n",
765                      get_khandle_from_ino(inode),
766                      inode->i_mode);
767
768         ret = orangefs_inode_setattr(inode, &wbattr);
769
770         return ret;
771 }
772
773 int orangefs_unmount_sb(struct super_block *sb)
774 {
775         int ret = -EINVAL;
776         struct orangefs_kernel_op_s *new_op = NULL;
777
778         gossip_debug(GOSSIP_UTILS_DEBUG,
779                      "orangefs_unmount_sb called on sb %p\n",
780                      sb);
781
782         new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
783         if (!new_op)
784                 return -ENOMEM;
785         new_op->upcall.req.fs_umount.id = ORANGEFS_SB(sb)->id;
786         new_op->upcall.req.fs_umount.fs_id = ORANGEFS_SB(sb)->fs_id;
787         strncpy(new_op->upcall.req.fs_umount.orangefs_config_server,
788                 ORANGEFS_SB(sb)->devname,
789                 ORANGEFS_MAX_SERVER_ADDR_LEN);
790
791         gossip_debug(GOSSIP_UTILS_DEBUG,
792                      "Attempting ORANGEFS Unmount via host %s\n",
793                      new_op->upcall.req.fs_umount.orangefs_config_server);
794
795         ret = service_operation(new_op, "orangefs_fs_umount", 0);
796
797         gossip_debug(GOSSIP_UTILS_DEBUG,
798                      "orangefs_unmount: got return value of %d\n", ret);
799         if (ret)
800                 sb = ERR_PTR(ret);
801         else
802                 ORANGEFS_SB(sb)->mount_pending = 1;
803
804         op_release(new_op);
805         return ret;
806 }
807
808 void orangefs_make_bad_inode(struct inode *inode)
809 {
810         if (is_root_handle(inode)) {
811                 /*
812                  * if this occurs, the pvfs2-client-core was killed but we
813                  * can't afford to lose the inode operations and such
814                  * associated with the root handle in any case.
815                  */
816                 gossip_debug(GOSSIP_UTILS_DEBUG,
817                              "*** NOT making bad root inode %pU\n",
818                              get_khandle_from_ino(inode));
819         } else {
820                 gossip_debug(GOSSIP_UTILS_DEBUG,
821                              "*** making bad inode %pU\n",
822                              get_khandle_from_ino(inode));
823                 make_bad_inode(inode);
824         }
825 }
826
827 /*
828  * The following is a very dirty hack that is now a permanent part of the
829  * ORANGEFS protocol. See protocol.h for more error definitions.
830  */
831
832 /* The order matches include/orangefs-types.h in the OrangeFS source. */
833 static int PINT_errno_mapping[] = {
834         0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
835         EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
836         EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
837         ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
838         EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
839         EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
840         ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
841         EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
842         ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
843         EACCES, ECONNRESET, ERANGE
844 };
845
846 int orangefs_normalize_to_errno(__s32 error_code)
847 {
848         __u32 i;
849
850         /* Success */
851         if (error_code == 0) {
852                 return 0;
853         /*
854          * This shouldn't ever happen. If it does it should be fixed on the
855          * server.
856          */
857         } else if (error_code > 0) {
858                 gossip_err("orangefs: error status receieved.\n");
859                 gossip_err("orangefs: assuming error code is inverted.\n");
860                 error_code = -error_code;
861         }
862
863         /*
864          * XXX: This is very bad since error codes from ORANGEFS may not be
865          * suitable for return into userspace.
866          */
867
868         /*
869          * Convert ORANGEFS error values into errno values suitable for return
870          * from the kernel.
871          */
872         if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
873                 if (((-error_code) &
874                     (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
875                     ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
876                         /*
877                          * cancellation error codes generally correspond to
878                          * a timeout from the client's perspective
879                          */
880                         error_code = -ETIMEDOUT;
881                 } else {
882                         /* assume a default error code */
883                         gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
884                         error_code = -EINVAL;
885                 }
886
887         /* Convert ORANGEFS encoded errno values into regular errno values. */
888         } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
889                 i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
890                 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
891                         error_code = -PINT_errno_mapping[i];
892                 else
893                         error_code = -EINVAL;
894
895         /*
896          * Only ORANGEFS protocol error codes should ever come here. Otherwise
897          * there is a bug somewhere.
898          */
899         } else {
900                 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
901         }
902         return error_code;
903 }
904
905 #define NUM_MODES 11
906 __s32 ORANGEFS_util_translate_mode(int mode)
907 {
908         int ret = 0;
909         int i = 0;
910         static int modes[NUM_MODES] = {
911                 S_IXOTH, S_IWOTH, S_IROTH,
912                 S_IXGRP, S_IWGRP, S_IRGRP,
913                 S_IXUSR, S_IWUSR, S_IRUSR,
914                 S_ISGID, S_ISUID
915         };
916         static int orangefs_modes[NUM_MODES] = {
917                 ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
918                 ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
919                 ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
920                 ORANGEFS_G_SGID, ORANGEFS_U_SUID
921         };
922
923         for (i = 0; i < NUM_MODES; i++)
924                 if (mode & modes[i])
925                         ret |= orangefs_modes[i];
926
927         return ret;
928 }
929 #undef NUM_MODES
930
931 /*
932  * After obtaining a string representation of the client's debug
933  * keywords and their associated masks, this function is called to build an
934  * array of these values.
935  */
936 int orangefs_prepare_cdm_array(char *debug_array_string)
937 {
938         int i;
939         int rc = -EINVAL;
940         char *cds_head = NULL;
941         char *cds_delimiter = NULL;
942         int keyword_len = 0;
943
944         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
945
946         /*
947          * figure out how many elements the cdm_array needs.
948          */
949         for (i = 0; i < strlen(debug_array_string); i++)
950                 if (debug_array_string[i] == '\n')
951                         cdm_element_count++;
952
953         if (!cdm_element_count) {
954                 pr_info("No elements in client debug array string!\n");
955                 goto out;
956         }
957
958         cdm_array =
959                 kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
960                         GFP_KERNEL);
961         if (!cdm_array) {
962                 pr_info("malloc failed for cdm_array!\n");
963                 rc = -ENOMEM;
964                 goto out;
965         }
966
967         cds_head = debug_array_string;
968
969         for (i = 0; i < cdm_element_count; i++) {
970                 cds_delimiter = strchr(cds_head, '\n');
971                 *cds_delimiter = '\0';
972
973                 keyword_len = strcspn(cds_head, " ");
974
975                 cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
976                 if (!cdm_array[i].keyword) {
977                         rc = -ENOMEM;
978                         goto out;
979                 }
980
981                 sscanf(cds_head,
982                        "%s %llx %llx",
983                        cdm_array[i].keyword,
984                        (unsigned long long *)&(cdm_array[i].mask1),
985                        (unsigned long long *)&(cdm_array[i].mask2));
986
987                 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
988                         client_verbose_index = i;
989
990                 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
991                         client_all_index = i;
992
993                 cds_head = cds_delimiter + 1;
994         }
995
996         rc = cdm_element_count;
997
998         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
999
1000 out:
1001
1002         return rc;
1003
1004 }
1005
1006 /*
1007  * /sys/kernel/debug/orangefs/debug-help can be catted to
1008  * see all the available kernel and client debug keywords.
1009  *
1010  * When the kernel boots, we have no idea what keywords the
1011  * client supports, nor their associated masks.
1012  *
1013  * We pass through this function once at boot and stamp a
1014  * boilerplate "we don't know" message for the client in the
1015  * debug-help file. We pass through here again when the client
1016  * starts and then we can fill out the debug-help file fully.
1017  *
1018  * The client might be restarted any number of times between
1019  * reboots, we only build the debug-help file the first time.
1020  */
1021 int orangefs_prepare_debugfs_help_string(int at_boot)
1022 {
1023         int rc = -EINVAL;
1024         int i;
1025         int byte_count = 0;
1026         char *client_title = "Client Debug Keywords:\n";
1027         char *kernel_title = "Kernel Debug Keywords:\n";
1028
1029         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1030
1031         if (at_boot) {
1032                 byte_count += strlen(HELP_STRING_UNINITIALIZED);
1033                 client_title = HELP_STRING_UNINITIALIZED;
1034         } else {
1035                 /*
1036                  * fill the client keyword/mask array and remember
1037                  * how many elements there were.
1038                  */
1039                 cdm_element_count =
1040                         orangefs_prepare_cdm_array(client_debug_array_string);
1041                 if (cdm_element_count <= 0)
1042                         goto out;
1043
1044                 /* Count the bytes destined for debug_help_string. */
1045                 byte_count += strlen(client_title);
1046
1047                 for (i = 0; i < cdm_element_count; i++) {
1048                         byte_count += strlen(cdm_array[i].keyword + 2);
1049                         if (byte_count >= DEBUG_HELP_STRING_SIZE) {
1050                                 pr_info("%s: overflow 1!\n", __func__);
1051                                 goto out;
1052                         }
1053                 }
1054
1055                 gossip_debug(GOSSIP_UTILS_DEBUG,
1056                              "%s: cdm_element_count:%d:\n",
1057                              __func__,
1058                              cdm_element_count);
1059         }
1060
1061         byte_count += strlen(kernel_title);
1062         for (i = 0; i < num_kmod_keyword_mask_map; i++) {
1063                 byte_count +=
1064                         strlen(s_kmod_keyword_mask_map[i].keyword + 2);
1065                 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
1066                         pr_info("%s: overflow 2!\n", __func__);
1067                         goto out;
1068                 }
1069         }
1070
1071         /* build debug_help_string. */
1072         debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
1073         if (!debug_help_string) {
1074                 rc = -ENOMEM;
1075                 goto out;
1076         }
1077
1078         strcat(debug_help_string, client_title);
1079
1080         if (!at_boot) {
1081                 for (i = 0; i < cdm_element_count; i++) {
1082                         strcat(debug_help_string, "\t");
1083                         strcat(debug_help_string, cdm_array[i].keyword);
1084                         strcat(debug_help_string, "\n");
1085                 }
1086         }
1087
1088         strcat(debug_help_string, "\n");
1089         strcat(debug_help_string, kernel_title);
1090
1091         for (i = 0; i < num_kmod_keyword_mask_map; i++) {
1092                 strcat(debug_help_string, "\t");
1093                 strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
1094                 strcat(debug_help_string, "\n");
1095         }
1096
1097         rc = 0;
1098
1099 out:
1100
1101         return rc;
1102
1103 }
1104
1105 /*
1106  * kernel = type 0
1107  * client = type 1
1108  */
1109 void debug_mask_to_string(void *mask, int type)
1110 {
1111         int i;
1112         int len = 0;
1113         char *debug_string;
1114         int element_count = 0;
1115
1116         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1117
1118         if (type) {
1119                 debug_string = client_debug_string;
1120                 element_count = cdm_element_count;
1121         } else {
1122                 debug_string = kernel_debug_string;
1123                 element_count = num_kmod_keyword_mask_map;
1124         }
1125
1126         memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
1127
1128         /*
1129          * Some keywords, like "all" or "verbose", are amalgams of
1130          * numerous other keywords. Make a special check for those
1131          * before grinding through the whole mask only to find out
1132          * later...
1133          */
1134         if (check_amalgam_keyword(mask, type))
1135                 goto out;
1136
1137         /* Build the debug string. */
1138         for (i = 0; i < element_count; i++)
1139                 if (type)
1140                         do_c_string(mask, i);
1141                 else
1142                         do_k_string(mask, i);
1143
1144         len = strlen(debug_string);
1145
1146         if ((len) && (type))
1147                 client_debug_string[len - 1] = '\0';
1148         else if (len)
1149                 kernel_debug_string[len - 1] = '\0';
1150         else if (type)
1151                 strcpy(client_debug_string, "none");
1152         else
1153                 strcpy(kernel_debug_string, "none");
1154
1155 out:
1156 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
1157
1158         return;
1159
1160 }
1161
1162 void do_k_string(void *k_mask, int index)
1163 {
1164         __u64 *mask = (__u64 *) k_mask;
1165
1166         if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
1167                 goto out;
1168
1169         if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
1170                 if ((strlen(kernel_debug_string) +
1171                      strlen(s_kmod_keyword_mask_map[index].keyword))
1172                         < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
1173                                 strcat(kernel_debug_string,
1174                                        s_kmod_keyword_mask_map[index].keyword);
1175                                 strcat(kernel_debug_string, ",");
1176                         } else {
1177                                 gossip_err("%s: overflow!\n", __func__);
1178                                 strcpy(kernel_debug_string, ORANGEFS_ALL);
1179                                 goto out;
1180                         }
1181         }
1182
1183 out:
1184
1185         return;
1186 }
1187
1188 void do_c_string(void *c_mask, int index)
1189 {
1190         struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
1191
1192         if (keyword_is_amalgam(cdm_array[index].keyword))
1193                 goto out;
1194
1195         if ((mask->mask1 & cdm_array[index].mask1) ||
1196             (mask->mask2 & cdm_array[index].mask2)) {
1197                 if ((strlen(client_debug_string) +
1198                      strlen(cdm_array[index].keyword) + 1)
1199                         < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
1200                                 strcat(client_debug_string,
1201                                        cdm_array[index].keyword);
1202                                 strcat(client_debug_string, ",");
1203                         } else {
1204                                 gossip_err("%s: overflow!\n", __func__);
1205                                 strcpy(client_debug_string, ORANGEFS_ALL);
1206                                 goto out;
1207                         }
1208         }
1209 out:
1210         return;
1211 }
1212
1213 int keyword_is_amalgam(char *keyword)
1214 {
1215         int rc = 0;
1216
1217         if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
1218                 rc = 1;
1219
1220         return rc;
1221 }
1222
1223 /*
1224  * kernel = type 0
1225  * client = type 1
1226  *
1227  * return 1 if we found an amalgam.
1228  */
1229 int check_amalgam_keyword(void *mask, int type)
1230 {
1231         __u64 *k_mask;
1232         struct client_debug_mask *c_mask;
1233         int k_all_index = num_kmod_keyword_mask_map - 1;
1234         int rc = 0;
1235
1236         if (type) {
1237                 c_mask = (struct client_debug_mask *) mask;
1238
1239                 if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
1240                     (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
1241                         strcpy(client_debug_string, ORANGEFS_ALL);
1242                         rc = 1;
1243                         goto out;
1244                 }
1245
1246                 if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
1247                     (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
1248                         strcpy(client_debug_string, ORANGEFS_VERBOSE);
1249                         rc = 1;
1250                         goto out;
1251                 }
1252
1253         } else {
1254                 k_mask = (__u64 *) mask;
1255
1256                 if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
1257                         strcpy(kernel_debug_string, ORANGEFS_ALL);
1258                         rc = 1;
1259                         goto out;
1260                 }
1261         }
1262
1263 out:
1264
1265         return rc;
1266 }
1267
1268 /*
1269  * kernel = type 0
1270  * client = type 1
1271  */
1272 void debug_string_to_mask(char *debug_string, void *mask, int type)
1273 {
1274         char *unchecked_keyword;
1275         int i;
1276         char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
1277         char *original_pointer;
1278         int element_count = 0;
1279         struct client_debug_mask *c_mask;
1280         __u64 *k_mask;
1281
1282         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1283
1284         if (type) {
1285                 c_mask = (struct client_debug_mask *)mask;
1286                 element_count = cdm_element_count;
1287         } else {
1288                 k_mask = (__u64 *)mask;
1289                 *k_mask = 0;
1290                 element_count = num_kmod_keyword_mask_map;
1291         }
1292
1293         original_pointer = strsep_fodder;
1294         while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
1295                 if (strlen(unchecked_keyword)) {
1296                         for (i = 0; i < element_count; i++)
1297                                 if (type)
1298                                         do_c_mask(i,
1299                                                   unchecked_keyword,
1300                                                   &c_mask);
1301                                 else
1302                                         do_k_mask(i,
1303                                                   unchecked_keyword,
1304                                                   &k_mask);
1305                 }
1306
1307         kfree(original_pointer);
1308 }
1309
1310 void do_c_mask(int i,
1311                char *unchecked_keyword,
1312                struct client_debug_mask **sane_mask)
1313 {
1314
1315         if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
1316                 (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
1317                 (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
1318         }
1319 }
1320
1321 void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
1322 {
1323
1324         if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
1325                 **sane_mask = (**sane_mask) |
1326                                 s_kmod_keyword_mask_map[i].mask_val;
1327 }