Merge remote-tracking branches 'asoc/topic/bcm2835', 'asoc/topic/cs42l56', 'asoc...
[cascardo/linux.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 /*
133  * NOTE: in kernel land, we never use the sys_attr->link_target for
134  * anything, so don't bother copying it into the sys_attr object here.
135  */
136 static inline int copy_attributes_from_inode(struct inode *inode,
137                                              struct ORANGEFS_sys_attr_s *attrs,
138                                              struct iattr *iattr)
139 {
140         umode_t tmp_mode;
141
142         if (!iattr || !inode || !attrs) {
143                 gossip_err("NULL iattr (%p), inode (%p), attrs (%p) "
144                            "in copy_attributes_from_inode!\n",
145                            iattr,
146                            inode,
147                            attrs);
148                 return -EINVAL;
149         }
150         /*
151          * We need to be careful to only copy the attributes out of the
152          * iattr object that we know are valid.
153          */
154         attrs->mask = 0;
155         if (iattr->ia_valid & ATTR_UID) {
156                 attrs->owner = from_kuid(current_user_ns(), iattr->ia_uid);
157                 attrs->mask |= ORANGEFS_ATTR_SYS_UID;
158                 gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
159         }
160         if (iattr->ia_valid & ATTR_GID) {
161                 attrs->group = from_kgid(current_user_ns(), iattr->ia_gid);
162                 attrs->mask |= ORANGEFS_ATTR_SYS_GID;
163                 gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
164         }
165
166         if (iattr->ia_valid & ATTR_ATIME) {
167                 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
168                 if (iattr->ia_valid & ATTR_ATIME_SET) {
169                         attrs->atime = (time64_t)iattr->ia_atime.tv_sec;
170                         attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
171                 }
172         }
173         if (iattr->ia_valid & ATTR_MTIME) {
174                 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
175                 if (iattr->ia_valid & ATTR_MTIME_SET) {
176                         attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec;
177                         attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
178                 }
179         }
180         if (iattr->ia_valid & ATTR_CTIME)
181                 attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
182
183         /*
184          * ORANGEFS cannot set size with a setattr operation.  Probably not likely
185          * to be requested through the VFS, but just in case, don't worry about
186          * ATTR_SIZE
187          */
188
189         if (iattr->ia_valid & ATTR_MODE) {
190                 tmp_mode = iattr->ia_mode;
191                 if (tmp_mode & (S_ISVTX)) {
192                         if (is_root_handle(inode)) {
193                                 /*
194                                  * allow sticky bit to be set on root (since
195                                  * it shows up that way by default anyhow),
196                                  * but don't show it to the server
197                                  */
198                                 tmp_mode -= S_ISVTX;
199                         } else {
200                                 gossip_debug(GOSSIP_UTILS_DEBUG,
201                                              "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
202                                 return -EINVAL;
203                         }
204                 }
205
206                 if (tmp_mode & (S_ISUID)) {
207                         gossip_debug(GOSSIP_UTILS_DEBUG,
208                                      "Attempting to set setuid bit (not supported); returning EINVAL.\n");
209                         return -EINVAL;
210                 }
211
212                 attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
213                 attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
214         }
215
216         return 0;
217 }
218
219 static int orangefs_inode_type(enum orangefs_ds_type objtype)
220 {
221         if (objtype == ORANGEFS_TYPE_METAFILE)
222                 return S_IFREG;
223         else if (objtype == ORANGEFS_TYPE_DIRECTORY)
224                 return S_IFDIR;
225         else if (objtype == ORANGEFS_TYPE_SYMLINK)
226                 return S_IFLNK;
227         else
228                 return -1;
229 }
230
231 static int orangefs_inode_is_stale(struct inode *inode, int new,
232     struct ORANGEFS_sys_attr_s *attrs, char *link_target)
233 {
234         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
235         int type = orangefs_inode_type(attrs->objtype);
236         if (!new) {
237                 /*
238                  * If the inode type or symlink target have changed then this
239                  * inode is stale.
240                  */
241                 if (type == -1 || !(inode->i_mode & type)) {
242                         orangefs_make_bad_inode(inode);
243                         return 1;
244                 }
245                 if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
246                     link_target, ORANGEFS_NAME_MAX)) {
247                         orangefs_make_bad_inode(inode);
248                         return 1;
249                 }
250         }
251         return 0;
252 }
253
254 int orangefs_inode_getattr(struct inode *inode, int new, int size)
255 {
256         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
257         struct orangefs_kernel_op_s *new_op;
258         loff_t inode_size, rounded_up_size;
259         int ret, type;
260
261         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
262             get_khandle_from_ino(inode));
263
264         new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
265         if (!new_op)
266                 return -ENOMEM;
267         new_op->upcall.req.getattr.refn = orangefs_inode->refn;
268         new_op->upcall.req.getattr.mask = size ?
269             ORANGEFS_ATTR_SYS_ALL_NOHINT : ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE;
270
271         ret = service_operation(new_op, __func__,
272             get_interruptible_flag(inode));
273         if (ret != 0)
274                 goto out;
275
276         type = orangefs_inode_type(new_op->
277             downcall.resp.getattr.attributes.objtype);
278         ret = orangefs_inode_is_stale(inode, new,
279             &new_op->downcall.resp.getattr.attributes,
280             new_op->downcall.resp.getattr.link_target);
281         if (ret) {
282                 ret = -ESTALE;
283                 goto out;
284         }
285
286         switch (type) {
287         case S_IFREG:
288                 inode->i_flags = orangefs_inode_flags(&new_op->
289                     downcall.resp.getattr.attributes);
290                 if (size) {
291                         inode_size = (loff_t)new_op->
292                             downcall.resp.getattr.attributes.size;
293                         rounded_up_size =
294                             (inode_size + (4096 - (inode_size % 4096)));
295                         inode->i_size = inode_size;
296                         orangefs_inode->blksize =
297                             new_op->downcall.resp.getattr.attributes.blksize;
298                         spin_lock(&inode->i_lock);
299                         inode->i_bytes = inode_size;
300                         inode->i_blocks =
301                             (unsigned long)(rounded_up_size / 512);
302                         spin_unlock(&inode->i_lock);
303                 }
304                 break;
305         case S_IFDIR:
306                 inode->i_size = PAGE_SIZE;
307                 orangefs_inode->blksize = (1 << inode->i_blkbits);
308                 spin_lock(&inode->i_lock);
309                 inode_set_bytes(inode, inode->i_size);
310                 spin_unlock(&inode->i_lock);
311                 set_nlink(inode, 1);
312                 break;
313         case S_IFLNK:
314                 if (new) {
315                         inode->i_size = (loff_t)strlen(new_op->
316                             downcall.resp.getattr.link_target);
317                         orangefs_inode->blksize = (1 << inode->i_blkbits);
318                         ret = strscpy(orangefs_inode->link_target,
319                             new_op->downcall.resp.getattr.link_target,
320                             ORANGEFS_NAME_MAX);
321                         if (ret == -E2BIG) {
322                                 ret = -EIO;
323                                 goto out;
324                         }
325                         inode->i_link = orangefs_inode->link_target;
326                 }
327                 break;
328         }
329
330         inode->i_uid = make_kuid(&init_user_ns, new_op->
331             downcall.resp.getattr.attributes.owner);
332         inode->i_gid = make_kgid(&init_user_ns, new_op->
333             downcall.resp.getattr.attributes.group);
334         inode->i_atime.tv_sec = (time64_t)new_op->
335             downcall.resp.getattr.attributes.atime;
336         inode->i_mtime.tv_sec = (time64_t)new_op->
337             downcall.resp.getattr.attributes.mtime;
338         inode->i_ctime.tv_sec = (time64_t)new_op->
339             downcall.resp.getattr.attributes.ctime;
340         inode->i_atime.tv_nsec = 0;
341         inode->i_mtime.tv_nsec = 0;
342         inode->i_ctime.tv_nsec = 0;
343
344         /* special case: mark the root inode as sticky */
345         inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
346             orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
347
348         ret = 0;
349 out:
350         op_release(new_op);
351         return ret;
352 }
353
354 int orangefs_inode_check_changed(struct inode *inode)
355 {
356         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
357         struct orangefs_kernel_op_s *new_op;
358         int ret;
359
360         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
361             get_khandle_from_ino(inode));
362
363         new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
364         if (!new_op)
365                 return -ENOMEM;
366         new_op->upcall.req.getattr.refn = orangefs_inode->refn;
367         new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
368             ORANGEFS_ATTR_SYS_LNK_TARGET;
369
370         ret = service_operation(new_op, __func__,
371             get_interruptible_flag(inode));
372         if (ret != 0)
373                 goto out;
374
375         ret = orangefs_inode_is_stale(inode, 0,
376             &new_op->downcall.resp.getattr.attributes,
377             new_op->downcall.resp.getattr.link_target);
378 out:
379         op_release(new_op);
380         return ret;
381 }
382
383 /*
384  * issues a orangefs setattr request to make sure the new attribute values
385  * take effect if successful.  returns 0 on success; -errno otherwise
386  */
387 int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
388 {
389         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
390         struct orangefs_kernel_op_s *new_op;
391         int ret;
392
393         new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
394         if (!new_op)
395                 return -ENOMEM;
396
397         new_op->upcall.req.setattr.refn = orangefs_inode->refn;
398         ret = copy_attributes_from_inode(inode,
399                        &new_op->upcall.req.setattr.attributes,
400                        iattr);
401         if (ret >= 0) {
402                 ret = service_operation(new_op, __func__,
403                                 get_interruptible_flag(inode));
404
405                 gossip_debug(GOSSIP_UTILS_DEBUG,
406                              "orangefs_inode_setattr: returning %d\n",
407                              ret);
408         }
409
410         op_release(new_op);
411
412         /*
413          * successful setattr should clear the atime, mtime and
414          * ctime flags.
415          */
416         if (ret == 0) {
417                 ClearAtimeFlag(orangefs_inode);
418                 ClearMtimeFlag(orangefs_inode);
419                 ClearCtimeFlag(orangefs_inode);
420                 ClearModeFlag(orangefs_inode);
421         }
422
423         return ret;
424 }
425
426 int orangefs_flush_inode(struct inode *inode)
427 {
428         /*
429          * If it is a dirty inode, this function gets called.
430          * Gather all the information that needs to be setattr'ed
431          * Right now, this will only be used for mode, atime, mtime
432          * and/or ctime.
433          */
434         struct iattr wbattr;
435         int ret;
436         int mtime_flag;
437         int ctime_flag;
438         int atime_flag;
439         int mode_flag;
440         struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
441
442         memset(&wbattr, 0, sizeof(wbattr));
443
444         /*
445          * check inode flags up front, and clear them if they are set.  This
446          * will prevent multiple processes from all trying to flush the same
447          * inode if they call close() simultaneously
448          */
449         mtime_flag = MtimeFlag(orangefs_inode);
450         ClearMtimeFlag(orangefs_inode);
451         ctime_flag = CtimeFlag(orangefs_inode);
452         ClearCtimeFlag(orangefs_inode);
453         atime_flag = AtimeFlag(orangefs_inode);
454         ClearAtimeFlag(orangefs_inode);
455         mode_flag = ModeFlag(orangefs_inode);
456         ClearModeFlag(orangefs_inode);
457
458         /*  -- Lazy atime,mtime and ctime update --
459          * Note: all times are dictated by server in the new scheme
460          * and not by the clients
461          *
462          * Also mode updates are being handled now..
463          */
464
465         if (mtime_flag)
466                 wbattr.ia_valid |= ATTR_MTIME;
467         if (ctime_flag)
468                 wbattr.ia_valid |= ATTR_CTIME;
469         if (atime_flag)
470                 wbattr.ia_valid |= ATTR_ATIME;
471
472         if (mode_flag) {
473                 wbattr.ia_mode = inode->i_mode;
474                 wbattr.ia_valid |= ATTR_MODE;
475         }
476
477         gossip_debug(GOSSIP_UTILS_DEBUG,
478                      "*********** orangefs_flush_inode: %pU "
479                      "(ia_valid %d)\n",
480                      get_khandle_from_ino(inode),
481                      wbattr.ia_valid);
482         if (wbattr.ia_valid == 0) {
483                 gossip_debug(GOSSIP_UTILS_DEBUG,
484                              "orangefs_flush_inode skipping setattr()\n");
485                 return 0;
486         }
487
488         gossip_debug(GOSSIP_UTILS_DEBUG,
489                      "orangefs_flush_inode (%pU) writing mode %o\n",
490                      get_khandle_from_ino(inode),
491                      inode->i_mode);
492
493         ret = orangefs_inode_setattr(inode, &wbattr);
494
495         return ret;
496 }
497
498 int orangefs_unmount_sb(struct super_block *sb)
499 {
500         int ret = -EINVAL;
501         struct orangefs_kernel_op_s *new_op = NULL;
502
503         gossip_debug(GOSSIP_UTILS_DEBUG,
504                      "orangefs_unmount_sb called on sb %p\n",
505                      sb);
506
507         new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
508         if (!new_op)
509                 return -ENOMEM;
510         new_op->upcall.req.fs_umount.id = ORANGEFS_SB(sb)->id;
511         new_op->upcall.req.fs_umount.fs_id = ORANGEFS_SB(sb)->fs_id;
512         strncpy(new_op->upcall.req.fs_umount.orangefs_config_server,
513                 ORANGEFS_SB(sb)->devname,
514                 ORANGEFS_MAX_SERVER_ADDR_LEN);
515
516         gossip_debug(GOSSIP_UTILS_DEBUG,
517                      "Attempting ORANGEFS Unmount via host %s\n",
518                      new_op->upcall.req.fs_umount.orangefs_config_server);
519
520         ret = service_operation(new_op, "orangefs_fs_umount", 0);
521
522         gossip_debug(GOSSIP_UTILS_DEBUG,
523                      "orangefs_unmount: got return value of %d\n", ret);
524         if (ret)
525                 sb = ERR_PTR(ret);
526         else
527                 ORANGEFS_SB(sb)->mount_pending = 1;
528
529         op_release(new_op);
530         return ret;
531 }
532
533 void orangefs_make_bad_inode(struct inode *inode)
534 {
535         if (is_root_handle(inode)) {
536                 /*
537                  * if this occurs, the pvfs2-client-core was killed but we
538                  * can't afford to lose the inode operations and such
539                  * associated with the root handle in any case.
540                  */
541                 gossip_debug(GOSSIP_UTILS_DEBUG,
542                              "*** NOT making bad root inode %pU\n",
543                              get_khandle_from_ino(inode));
544         } else {
545                 gossip_debug(GOSSIP_UTILS_DEBUG,
546                              "*** making bad inode %pU\n",
547                              get_khandle_from_ino(inode));
548                 make_bad_inode(inode);
549         }
550 }
551
552 /*
553  * The following is a very dirty hack that is now a permanent part of the
554  * ORANGEFS protocol. See protocol.h for more error definitions.
555  */
556
557 /* The order matches include/orangefs-types.h in the OrangeFS source. */
558 static int PINT_errno_mapping[] = {
559         0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
560         EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
561         EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
562         ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
563         EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
564         EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
565         ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
566         EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
567         ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
568         EACCES, ECONNRESET, ERANGE
569 };
570
571 int orangefs_normalize_to_errno(__s32 error_code)
572 {
573         __u32 i;
574
575         /* Success */
576         if (error_code == 0) {
577                 return 0;
578         /*
579          * This shouldn't ever happen. If it does it should be fixed on the
580          * server.
581          */
582         } else if (error_code > 0) {
583                 gossip_err("orangefs: error status receieved.\n");
584                 gossip_err("orangefs: assuming error code is inverted.\n");
585                 error_code = -error_code;
586         }
587
588         /*
589          * XXX: This is very bad since error codes from ORANGEFS may not be
590          * suitable for return into userspace.
591          */
592
593         /*
594          * Convert ORANGEFS error values into errno values suitable for return
595          * from the kernel.
596          */
597         if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
598                 if (((-error_code) &
599                     (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
600                     ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
601                         /*
602                          * cancellation error codes generally correspond to
603                          * a timeout from the client's perspective
604                          */
605                         error_code = -ETIMEDOUT;
606                 } else {
607                         /* assume a default error code */
608                         gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
609                         error_code = -EINVAL;
610                 }
611
612         /* Convert ORANGEFS encoded errno values into regular errno values. */
613         } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
614                 i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
615                 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
616                         error_code = -PINT_errno_mapping[i];
617                 else
618                         error_code = -EINVAL;
619
620         /*
621          * Only ORANGEFS protocol error codes should ever come here. Otherwise
622          * there is a bug somewhere.
623          */
624         } else {
625                 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
626         }
627         return error_code;
628 }
629
630 #define NUM_MODES 11
631 __s32 ORANGEFS_util_translate_mode(int mode)
632 {
633         int ret = 0;
634         int i = 0;
635         static int modes[NUM_MODES] = {
636                 S_IXOTH, S_IWOTH, S_IROTH,
637                 S_IXGRP, S_IWGRP, S_IRGRP,
638                 S_IXUSR, S_IWUSR, S_IRUSR,
639                 S_ISGID, S_ISUID
640         };
641         static int orangefs_modes[NUM_MODES] = {
642                 ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
643                 ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
644                 ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
645                 ORANGEFS_G_SGID, ORANGEFS_U_SUID
646         };
647
648         for (i = 0; i < NUM_MODES; i++)
649                 if (mode & modes[i])
650                         ret |= orangefs_modes[i];
651
652         return ret;
653 }
654 #undef NUM_MODES
655
656 /*
657  * After obtaining a string representation of the client's debug
658  * keywords and their associated masks, this function is called to build an
659  * array of these values.
660  */
661 int orangefs_prepare_cdm_array(char *debug_array_string)
662 {
663         int i;
664         int rc = -EINVAL;
665         char *cds_head = NULL;
666         char *cds_delimiter = NULL;
667         int keyword_len = 0;
668
669         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
670
671         /*
672          * figure out how many elements the cdm_array needs.
673          */
674         for (i = 0; i < strlen(debug_array_string); i++)
675                 if (debug_array_string[i] == '\n')
676                         cdm_element_count++;
677
678         if (!cdm_element_count) {
679                 pr_info("No elements in client debug array string!\n");
680                 goto out;
681         }
682
683         cdm_array =
684                 kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
685                         GFP_KERNEL);
686         if (!cdm_array) {
687                 pr_info("malloc failed for cdm_array!\n");
688                 rc = -ENOMEM;
689                 goto out;
690         }
691
692         cds_head = debug_array_string;
693
694         for (i = 0; i < cdm_element_count; i++) {
695                 cds_delimiter = strchr(cds_head, '\n');
696                 *cds_delimiter = '\0';
697
698                 keyword_len = strcspn(cds_head, " ");
699
700                 cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
701                 if (!cdm_array[i].keyword) {
702                         rc = -ENOMEM;
703                         goto out;
704                 }
705
706                 sscanf(cds_head,
707                        "%s %llx %llx",
708                        cdm_array[i].keyword,
709                        (unsigned long long *)&(cdm_array[i].mask1),
710                        (unsigned long long *)&(cdm_array[i].mask2));
711
712                 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
713                         client_verbose_index = i;
714
715                 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
716                         client_all_index = i;
717
718                 cds_head = cds_delimiter + 1;
719         }
720
721         rc = cdm_element_count;
722
723         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
724
725 out:
726
727         return rc;
728
729 }
730
731 /*
732  * /sys/kernel/debug/orangefs/debug-help can be catted to
733  * see all the available kernel and client debug keywords.
734  *
735  * When the kernel boots, we have no idea what keywords the
736  * client supports, nor their associated masks.
737  *
738  * We pass through this function once at boot and stamp a
739  * boilerplate "we don't know" message for the client in the
740  * debug-help file. We pass through here again when the client
741  * starts and then we can fill out the debug-help file fully.
742  *
743  * The client might be restarted any number of times between
744  * reboots, we only build the debug-help file the first time.
745  */
746 int orangefs_prepare_debugfs_help_string(int at_boot)
747 {
748         int rc = -EINVAL;
749         int i;
750         int byte_count = 0;
751         char *client_title = "Client Debug Keywords:\n";
752         char *kernel_title = "Kernel Debug Keywords:\n";
753
754         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
755
756         if (at_boot) {
757                 byte_count += strlen(HELP_STRING_UNINITIALIZED);
758                 client_title = HELP_STRING_UNINITIALIZED;
759         } else {
760                 /*
761                  * fill the client keyword/mask array and remember
762                  * how many elements there were.
763                  */
764                 cdm_element_count =
765                         orangefs_prepare_cdm_array(client_debug_array_string);
766                 if (cdm_element_count <= 0)
767                         goto out;
768
769                 /* Count the bytes destined for debug_help_string. */
770                 byte_count += strlen(client_title);
771
772                 for (i = 0; i < cdm_element_count; i++) {
773                         byte_count += strlen(cdm_array[i].keyword + 2);
774                         if (byte_count >= DEBUG_HELP_STRING_SIZE) {
775                                 pr_info("%s: overflow 1!\n", __func__);
776                                 goto out;
777                         }
778                 }
779
780                 gossip_debug(GOSSIP_UTILS_DEBUG,
781                              "%s: cdm_element_count:%d:\n",
782                              __func__,
783                              cdm_element_count);
784         }
785
786         byte_count += strlen(kernel_title);
787         for (i = 0; i < num_kmod_keyword_mask_map; i++) {
788                 byte_count +=
789                         strlen(s_kmod_keyword_mask_map[i].keyword + 2);
790                 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
791                         pr_info("%s: overflow 2!\n", __func__);
792                         goto out;
793                 }
794         }
795
796         /* build debug_help_string. */
797         debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
798         if (!debug_help_string) {
799                 rc = -ENOMEM;
800                 goto out;
801         }
802
803         strcat(debug_help_string, client_title);
804
805         if (!at_boot) {
806                 for (i = 0; i < cdm_element_count; i++) {
807                         strcat(debug_help_string, "\t");
808                         strcat(debug_help_string, cdm_array[i].keyword);
809                         strcat(debug_help_string, "\n");
810                 }
811         }
812
813         strcat(debug_help_string, "\n");
814         strcat(debug_help_string, kernel_title);
815
816         for (i = 0; i < num_kmod_keyword_mask_map; i++) {
817                 strcat(debug_help_string, "\t");
818                 strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
819                 strcat(debug_help_string, "\n");
820         }
821
822         rc = 0;
823
824 out:
825
826         return rc;
827
828 }
829
830 /*
831  * kernel = type 0
832  * client = type 1
833  */
834 void debug_mask_to_string(void *mask, int type)
835 {
836         int i;
837         int len = 0;
838         char *debug_string;
839         int element_count = 0;
840
841         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
842
843         if (type) {
844                 debug_string = client_debug_string;
845                 element_count = cdm_element_count;
846         } else {
847                 debug_string = kernel_debug_string;
848                 element_count = num_kmod_keyword_mask_map;
849         }
850
851         memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
852
853         /*
854          * Some keywords, like "all" or "verbose", are amalgams of
855          * numerous other keywords. Make a special check for those
856          * before grinding through the whole mask only to find out
857          * later...
858          */
859         if (check_amalgam_keyword(mask, type))
860                 goto out;
861
862         /* Build the debug string. */
863         for (i = 0; i < element_count; i++)
864                 if (type)
865                         do_c_string(mask, i);
866                 else
867                         do_k_string(mask, i);
868
869         len = strlen(debug_string);
870
871         if ((len) && (type))
872                 client_debug_string[len - 1] = '\0';
873         else if (len)
874                 kernel_debug_string[len - 1] = '\0';
875         else if (type)
876                 strcpy(client_debug_string, "none");
877         else
878                 strcpy(kernel_debug_string, "none");
879
880 out:
881 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
882
883         return;
884
885 }
886
887 void do_k_string(void *k_mask, int index)
888 {
889         __u64 *mask = (__u64 *) k_mask;
890
891         if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
892                 goto out;
893
894         if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
895                 if ((strlen(kernel_debug_string) +
896                      strlen(s_kmod_keyword_mask_map[index].keyword))
897                         < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
898                                 strcat(kernel_debug_string,
899                                        s_kmod_keyword_mask_map[index].keyword);
900                                 strcat(kernel_debug_string, ",");
901                         } else {
902                                 gossip_err("%s: overflow!\n", __func__);
903                                 strcpy(kernel_debug_string, ORANGEFS_ALL);
904                                 goto out;
905                         }
906         }
907
908 out:
909
910         return;
911 }
912
913 void do_c_string(void *c_mask, int index)
914 {
915         struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
916
917         if (keyword_is_amalgam(cdm_array[index].keyword))
918                 goto out;
919
920         if ((mask->mask1 & cdm_array[index].mask1) ||
921             (mask->mask2 & cdm_array[index].mask2)) {
922                 if ((strlen(client_debug_string) +
923                      strlen(cdm_array[index].keyword) + 1)
924                         < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
925                                 strcat(client_debug_string,
926                                        cdm_array[index].keyword);
927                                 strcat(client_debug_string, ",");
928                         } else {
929                                 gossip_err("%s: overflow!\n", __func__);
930                                 strcpy(client_debug_string, ORANGEFS_ALL);
931                                 goto out;
932                         }
933         }
934 out:
935         return;
936 }
937
938 int keyword_is_amalgam(char *keyword)
939 {
940         int rc = 0;
941
942         if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
943                 rc = 1;
944
945         return rc;
946 }
947
948 /*
949  * kernel = type 0
950  * client = type 1
951  *
952  * return 1 if we found an amalgam.
953  */
954 int check_amalgam_keyword(void *mask, int type)
955 {
956         __u64 *k_mask;
957         struct client_debug_mask *c_mask;
958         int k_all_index = num_kmod_keyword_mask_map - 1;
959         int rc = 0;
960
961         if (type) {
962                 c_mask = (struct client_debug_mask *) mask;
963
964                 if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
965                     (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
966                         strcpy(client_debug_string, ORANGEFS_ALL);
967                         rc = 1;
968                         goto out;
969                 }
970
971                 if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
972                     (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
973                         strcpy(client_debug_string, ORANGEFS_VERBOSE);
974                         rc = 1;
975                         goto out;
976                 }
977
978         } else {
979                 k_mask = (__u64 *) mask;
980
981                 if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
982                         strcpy(kernel_debug_string, ORANGEFS_ALL);
983                         rc = 1;
984                         goto out;
985                 }
986         }
987
988 out:
989
990         return rc;
991 }
992
993 /*
994  * kernel = type 0
995  * client = type 1
996  */
997 void debug_string_to_mask(char *debug_string, void *mask, int type)
998 {
999         char *unchecked_keyword;
1000         int i;
1001         char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
1002         char *original_pointer;
1003         int element_count = 0;
1004         struct client_debug_mask *c_mask;
1005         __u64 *k_mask;
1006
1007         gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1008
1009         if (type) {
1010                 c_mask = (struct client_debug_mask *)mask;
1011                 element_count = cdm_element_count;
1012         } else {
1013                 k_mask = (__u64 *)mask;
1014                 *k_mask = 0;
1015                 element_count = num_kmod_keyword_mask_map;
1016         }
1017
1018         original_pointer = strsep_fodder;
1019         while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
1020                 if (strlen(unchecked_keyword)) {
1021                         for (i = 0; i < element_count; i++)
1022                                 if (type)
1023                                         do_c_mask(i,
1024                                                   unchecked_keyword,
1025                                                   &c_mask);
1026                                 else
1027                                         do_k_mask(i,
1028                                                   unchecked_keyword,
1029                                                   &k_mask);
1030                 }
1031
1032         kfree(original_pointer);
1033 }
1034
1035 void do_c_mask(int i,
1036                char *unchecked_keyword,
1037                struct client_debug_mask **sane_mask)
1038 {
1039
1040         if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
1041                 (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
1042                 (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
1043         }
1044 }
1045
1046 void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
1047 {
1048
1049         if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
1050                 **sane_mask = (**sane_mask) |
1051                                 s_kmod_keyword_mask_map[i].mask_val;
1052 }