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