orangefs: use new getattr for revalidate and remove old getattr
[deliverable/linux.git] / fs / orangefs / orangefs-utils.c
CommitLineData
f7be4ee0
MM
1/*
2 * (C) 2001 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6#include "protocol.h"
575e9461
MM
7#include "orangefs-kernel.h"
8#include "orangefs-dev-proto.h"
9#include "orangefs-bufmap.h"
f7be4ee0 10
8bb8aefd 11__s32 fsid_of_op(struct orangefs_kernel_op_s *op)
f7be4ee0 12{
8bb8aefd 13 __s32 fsid = ORANGEFS_FS_ID_NULL;
f7be4ee0
MM
14
15 if (op) {
16 switch (op->upcall.type) {
8bb8aefd 17 case ORANGEFS_VFS_OP_FILE_IO:
f7be4ee0
MM
18 fsid = op->upcall.req.io.refn.fs_id;
19 break;
8bb8aefd 20 case ORANGEFS_VFS_OP_LOOKUP:
f7be4ee0
MM
21 fsid = op->upcall.req.lookup.parent_refn.fs_id;
22 break;
8bb8aefd 23 case ORANGEFS_VFS_OP_CREATE:
f7be4ee0
MM
24 fsid = op->upcall.req.create.parent_refn.fs_id;
25 break;
8bb8aefd 26 case ORANGEFS_VFS_OP_GETATTR:
f7be4ee0
MM
27 fsid = op->upcall.req.getattr.refn.fs_id;
28 break;
8bb8aefd 29 case ORANGEFS_VFS_OP_REMOVE:
f7be4ee0
MM
30 fsid = op->upcall.req.remove.parent_refn.fs_id;
31 break;
8bb8aefd 32 case ORANGEFS_VFS_OP_MKDIR:
f7be4ee0
MM
33 fsid = op->upcall.req.mkdir.parent_refn.fs_id;
34 break;
8bb8aefd 35 case ORANGEFS_VFS_OP_READDIR:
f7be4ee0
MM
36 fsid = op->upcall.req.readdir.refn.fs_id;
37 break;
8bb8aefd 38 case ORANGEFS_VFS_OP_SETATTR:
f7be4ee0
MM
39 fsid = op->upcall.req.setattr.refn.fs_id;
40 break;
8bb8aefd 41 case ORANGEFS_VFS_OP_SYMLINK:
f7be4ee0
MM
42 fsid = op->upcall.req.sym.parent_refn.fs_id;
43 break;
8bb8aefd 44 case ORANGEFS_VFS_OP_RENAME:
f7be4ee0
MM
45 fsid = op->upcall.req.rename.old_parent_refn.fs_id;
46 break;
8bb8aefd 47 case ORANGEFS_VFS_OP_STATFS:
f7be4ee0
MM
48 fsid = op->upcall.req.statfs.fs_id;
49 break;
8bb8aefd 50 case ORANGEFS_VFS_OP_TRUNCATE:
f7be4ee0
MM
51 fsid = op->upcall.req.truncate.refn.fs_id;
52 break;
8bb8aefd 53 case ORANGEFS_VFS_OP_MMAP_RA_FLUSH:
f7be4ee0
MM
54 fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
55 break;
8bb8aefd 56 case ORANGEFS_VFS_OP_FS_UMOUNT:
f7be4ee0
MM
57 fsid = op->upcall.req.fs_umount.fs_id;
58 break;
8bb8aefd 59 case ORANGEFS_VFS_OP_GETXATTR:
f7be4ee0
MM
60 fsid = op->upcall.req.getxattr.refn.fs_id;
61 break;
8bb8aefd 62 case ORANGEFS_VFS_OP_SETXATTR:
f7be4ee0
MM
63 fsid = op->upcall.req.setxattr.refn.fs_id;
64 break;
8bb8aefd 65 case ORANGEFS_VFS_OP_LISTXATTR:
f7be4ee0
MM
66 fsid = op->upcall.req.listxattr.refn.fs_id;
67 break;
8bb8aefd 68 case ORANGEFS_VFS_OP_REMOVEXATTR:
f7be4ee0
MM
69 fsid = op->upcall.req.removexattr.refn.fs_id;
70 break;
8bb8aefd 71 case ORANGEFS_VFS_OP_FSYNC:
f7be4ee0
MM
72 fsid = op->upcall.req.fsync.refn.fs_id;
73 break;
74 default:
75 break;
76 }
77 }
78 return fsid;
79}
80
394f647e 81static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
f7be4ee0 82{
394f647e 83 int flags = 0;
8bb8aefd 84 if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
394f647e 85 flags |= S_IMMUTABLE;
f7be4ee0 86 else
394f647e 87 flags &= ~S_IMMUTABLE;
8bb8aefd 88 if (attrs->flags & ORANGEFS_APPEND_FL)
394f647e 89 flags |= S_APPEND;
f7be4ee0 90 else
394f647e 91 flags &= ~S_APPEND;
8bb8aefd 92 if (attrs->flags & ORANGEFS_NOATIME_FL)
394f647e 93 flags |= S_NOATIME;
f7be4ee0 94 else
394f647e
MB
95 flags &= ~S_NOATIME;
96 return flags;
97}
98
99static 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;
f7be4ee0 116
394f647e
MB
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;
f7be4ee0
MM
130}
131
f7be4ee0
MM
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 */
136static inline int copy_attributes_from_inode(struct inode *inode,
8bb8aefd 137 struct ORANGEFS_sys_attr_s *attrs,
f7be4ee0
MM
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);
8bb8aefd 157 attrs->mask |= ORANGEFS_ATTR_SYS_UID;
f7be4ee0
MM
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);
8bb8aefd 162 attrs->mask |= ORANGEFS_ATTR_SYS_GID;
f7be4ee0
MM
163 gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
164 }
165
166 if (iattr->ia_valid & ATTR_ATIME) {
8bb8aefd 167 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
f7be4ee0 168 if (iattr->ia_valid & ATTR_ATIME_SET) {
be81ce48 169 attrs->atime = (time64_t)iattr->ia_atime.tv_sec;
8bb8aefd 170 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
f7be4ee0
MM
171 }
172 }
173 if (iattr->ia_valid & ATTR_MTIME) {
8bb8aefd 174 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
f7be4ee0 175 if (iattr->ia_valid & ATTR_MTIME_SET) {
be81ce48 176 attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec;
8bb8aefd 177 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
f7be4ee0
MM
178 }
179 }
180 if (iattr->ia_valid & ATTR_CTIME)
8bb8aefd 181 attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
f7be4ee0
MM
182
183 /*
8bb8aefd 184 * ORANGEFS cannot set size with a setattr operation. Probably not likely
f7be4ee0
MM
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
8bb8aefd
YL
212 attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
213 attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
f7be4ee0
MM
214 }
215
216 return 0;
217}
218
3c9cf98d
MB
219static 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
231int orangefs_inode_getattr(struct inode *inode, int new, int size)
232{
233 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
234 struct orangefs_kernel_op_s *new_op;
235 loff_t inode_size, rounded_up_size;
236 int ret;
237
238 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
239 get_khandle_from_ino(inode));
240
241 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
242 if (!new_op)
243 return -ENOMEM;
244 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
245 new_op->upcall.req.getattr.mask = size ?
246 ORANGEFS_ATTR_SYS_ALL_NOHINT : ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE;
247
248 ret = service_operation(new_op, __func__,
249 get_interruptible_flag(inode));
250 if (ret != 0)
251 goto out;
252
253 ret = orangefs_inode_type(new_op->
254 downcall.resp.getattr.attributes.objtype);
255 if (!new) {
256 /*
257 * If the inode type or symlink target have changed then this
258 * inode is stale.
259 */
260 if (ret == -1 || !(inode->i_mode & ret)) {
261 orangefs_make_bad_inode(inode);
262 ret = -ESTALE;
263 goto out;
264 }
265 if (ret == S_IFLNK && strncmp(orangefs_inode->link_target,
266 new_op->downcall.resp.getattr.link_target,
267 ORANGEFS_NAME_MAX)) {
268 orangefs_make_bad_inode(inode);
269 ret = -ESTALE;
270 goto out;
271 }
272 }
273
274 switch (ret) {
275 case S_IFREG:
276 inode->i_flags = orangefs_inode_flags(&new_op->
277 downcall.resp.getattr.attributes);
278 if (size) {
279 inode_size = (loff_t)new_op->
280 downcall.resp.getattr.attributes.size;
281 rounded_up_size =
282 (inode_size + (4096 - (inode_size % 4096)));
283 inode->i_size = inode_size;
284 orangefs_inode->blksize =
285 new_op->downcall.resp.getattr.attributes.blksize;
286 spin_lock(&inode->i_lock);
287 inode->i_bytes = inode_size;
288 inode->i_blocks =
289 (unsigned long)(rounded_up_size / 512);
290 spin_unlock(&inode->i_lock);
291 }
292 break;
293 case S_IFDIR:
294 inode->i_size = PAGE_CACHE_SIZE;
295 orangefs_inode->blksize = (1 << inode->i_blkbits);
296 spin_lock(&inode->i_lock);
297 inode_set_bytes(inode, inode->i_size);
298 spin_unlock(&inode->i_lock);
299 set_nlink(inode, 1);
300 break;
301 case S_IFLNK:
302 if (new) {
303 inode->i_size = (loff_t)strlen(new_op->
304 downcall.resp.getattr.link_target);
305 orangefs_inode->blksize = (1 << inode->i_blkbits);
306 strlcpy(orangefs_inode->link_target,
307 new_op->downcall.resp.getattr.link_target,
308 ORANGEFS_NAME_MAX);
309 }
310 break;
311 }
312
313 inode->i_uid = make_kuid(&init_user_ns, new_op->
314 downcall.resp.getattr.attributes.owner);
315 inode->i_gid = make_kgid(&init_user_ns, new_op->
316 downcall.resp.getattr.attributes.group);
317 inode->i_atime.tv_sec = (time64_t)new_op->
318 downcall.resp.getattr.attributes.atime;
319 inode->i_mtime.tv_sec = (time64_t)new_op->
320 downcall.resp.getattr.attributes.mtime;
321 inode->i_ctime.tv_sec = (time64_t)new_op->
322 downcall.resp.getattr.attributes.ctime;
323 inode->i_atime.tv_nsec = 0;
324 inode->i_mtime.tv_nsec = 0;
325 inode->i_ctime.tv_nsec = 0;
326
327 /* special case: mark the root inode as sticky */
328 inode->i_mode = ret | (is_root_handle(inode) ? S_ISVTX : 0) |
329 orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
330
331 ret = 0;
332out:
333 op_release(new_op);
334 return ret;
335}
336
5859d77e
MB
337int orangefs_inode_check_changed(struct inode *inode)
338{
339 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
340 struct orangefs_kernel_op_s *new_op;
341 int ret;
342
343 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
344 get_khandle_from_ino(inode));
345
346 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
347 if (!new_op)
348 return -ENOMEM;
349 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
350 new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
351 ORANGEFS_ATTR_SYS_LNK_TARGET;
352
353 ret = service_operation(new_op, __func__,
354 get_interruptible_flag(inode));
355 if (ret != 0)
356 goto out;
357
358 ret = orangefs_inode_type(new_op->
359 downcall.resp.getattr.attributes.objtype);
360 /*
361 * If the inode type or symlink target have changed then this
362 * inode is stale.
363 */
364 if (ret == -1 || !(inode->i_mode & ret)) {
365 orangefs_make_bad_inode(inode);
366 ret = 1;
367 goto out;
368 }
369 if (ret == S_IFLNK && strncmp(orangefs_inode->link_target,
370 new_op->downcall.resp.getattr.link_target,
371 ORANGEFS_NAME_MAX)) {
372 orangefs_make_bad_inode(inode);
373 ret = 1;
374 goto out;
375 }
376
377 ret = 0;
378out:
379 op_release(new_op);
380 return ret;
381}
382
f7be4ee0 383/*
8bb8aefd 384 * issues a orangefs setattr request to make sure the new attribute values
f7be4ee0
MM
385 * take effect if successful. returns 0 on success; -errno otherwise
386 */
8bb8aefd 387int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
f7be4ee0 388{
8bb8aefd
YL
389 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
390 struct orangefs_kernel_op_s *new_op;
f7be4ee0
MM
391 int ret;
392
8bb8aefd 393 new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
f7be4ee0
MM
394 if (!new_op)
395 return -ENOMEM;
396
8bb8aefd 397 new_op->upcall.req.setattr.refn = orangefs_inode->refn;
f7be4ee0
MM
398 ret = copy_attributes_from_inode(inode,
399 &new_op->upcall.req.setattr.attributes,
400 iattr);
ed42fe05
AV
401 if (ret >= 0) {
402 ret = service_operation(new_op, __func__,
f7be4ee0
MM
403 get_interruptible_flag(inode));
404
ed42fe05
AV
405 gossip_debug(GOSSIP_UTILS_DEBUG,
406 "orangefs_inode_setattr: returning %d\n",
407 ret);
408 }
f7be4ee0 409
f7be4ee0
MM
410 op_release(new_op);
411
412 /*
413 * successful setattr should clear the atime, mtime and
414 * ctime flags.
415 */
416 if (ret == 0) {
8bb8aefd
YL
417 ClearAtimeFlag(orangefs_inode);
418 ClearMtimeFlag(orangefs_inode);
419 ClearCtimeFlag(orangefs_inode);
420 ClearModeFlag(orangefs_inode);
f7be4ee0
MM
421 }
422
423 return ret;
424}
425
8bb8aefd 426int orangefs_flush_inode(struct inode *inode)
f7be4ee0
MM
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;
8bb8aefd 440 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
f7be4ee0
MM
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 */
8bb8aefd
YL
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);
f7be4ee0
MM
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,
8bb8aefd 478 "*********** orangefs_flush_inode: %pU "
f7be4ee0
MM
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,
8bb8aefd 484 "orangefs_flush_inode skipping setattr()\n");
f7be4ee0
MM
485 return 0;
486 }
487
488 gossip_debug(GOSSIP_UTILS_DEBUG,
8bb8aefd 489 "orangefs_flush_inode (%pU) writing mode %o\n",
f7be4ee0
MM
490 get_khandle_from_ino(inode),
491 inode->i_mode);
492
8bb8aefd 493 ret = orangefs_inode_setattr(inode, &wbattr);
f7be4ee0
MM
494
495 return ret;
496}
497
8bb8aefd 498int orangefs_unmount_sb(struct super_block *sb)
f7be4ee0
MM
499{
500 int ret = -EINVAL;
8bb8aefd 501 struct orangefs_kernel_op_s *new_op = NULL;
f7be4ee0
MM
502
503 gossip_debug(GOSSIP_UTILS_DEBUG,
8bb8aefd 504 "orangefs_unmount_sb called on sb %p\n",
f7be4ee0
MM
505 sb);
506
8bb8aefd 507 new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
f7be4ee0
MM
508 if (!new_op)
509 return -ENOMEM;
8bb8aefd
YL
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);
f7be4ee0
MM
515
516 gossip_debug(GOSSIP_UTILS_DEBUG,
8bb8aefd
YL
517 "Attempting ORANGEFS Unmount via host %s\n",
518 new_op->upcall.req.fs_umount.orangefs_config_server);
f7be4ee0 519
8bb8aefd 520 ret = service_operation(new_op, "orangefs_fs_umount", 0);
f7be4ee0
MM
521
522 gossip_debug(GOSSIP_UTILS_DEBUG,
8bb8aefd 523 "orangefs_unmount: got return value of %d\n", ret);
f7be4ee0
MM
524 if (ret)
525 sb = ERR_PTR(ret);
526 else
8bb8aefd 527 ORANGEFS_SB(sb)->mount_pending = 1;
f7be4ee0
MM
528
529 op_release(new_op);
530 return ret;
531}
532
8bb8aefd 533void orangefs_make_bad_inode(struct inode *inode)
f7be4ee0
MM
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
54804949
MM
552/*
553 * The following is a very dirty hack that is now a permanent part of the
8bb8aefd 554 * ORANGEFS protocol. See protocol.h for more error definitions.
54804949 555 */
894ac432 556
8bb8aefd 557/* The order matches include/orangefs-types.h in the OrangeFS source. */
894ac432 558static int PINT_errno_mapping[] = {
54804949
MM
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
894ac432 569};
f7be4ee0 570
8bb8aefd 571int orangefs_normalize_to_errno(__s32 error_code)
f7be4ee0 572{
54804949
MM
573 __u32 i;
574
894ac432
MB
575 /* Success */
576 if (error_code == 0) {
577 return 0;
54804949
MM
578 /*
579 * This shouldn't ever happen. If it does it should be fixed on the
580 * server.
581 */
894ac432 582 } else if (error_code > 0) {
8bb8aefd
YL
583 gossip_err("orangefs: error status receieved.\n");
584 gossip_err("orangefs: assuming error code is inverted.\n");
f7be4ee0
MM
585 error_code = -error_code;
586 }
587
54804949 588 /*
8bb8aefd 589 * XXX: This is very bad since error codes from ORANGEFS may not be
54804949
MM
590 * suitable for return into userspace.
591 */
894ac432 592
54804949 593 /*
8bb8aefd 594 * Convert ORANGEFS error values into errno values suitable for return
54804949
MM
595 * from the kernel.
596 */
8bb8aefd 597 if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
894ac432 598 if (((-error_code) &
8bb8aefd
YL
599 (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
600 ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
f7be4ee0
MM
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 */
8bb8aefd 608 gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
f7be4ee0
MM
609 error_code = -EINVAL;
610 }
894ac432 611
8bb8aefd
YL
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);
54804949 615 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
894ac432
MB
616 error_code = -PINT_errno_mapping[i];
617 else
618 error_code = -EINVAL;
619
54804949 620 /*
8bb8aefd 621 * Only ORANGEFS protocol error codes should ever come here. Otherwise
54804949
MM
622 * there is a bug somewhere.
623 */
894ac432 624 } else {
8bb8aefd 625 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
f7be4ee0
MM
626 }
627 return error_code;
628}
629
630#define NUM_MODES 11
8bb8aefd 631__s32 ORANGEFS_util_translate_mode(int mode)
f7be4ee0
MM
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 };
8bb8aefd
YL
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
f7be4ee0
MM
646 };
647
648 for (i = 0; i < NUM_MODES; i++)
649 if (mode & modes[i])
8bb8aefd 650 ret |= orangefs_modes[i];
f7be4ee0
MM
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 */
661int 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
8bb8aefd 712 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
f7be4ee0
MM
713 client_verbose_index = i;
714
8bb8aefd 715 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
f7be4ee0
MM
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
725out:
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 */
746int 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
824out:
825
826 return rc;
827
828}
829
830/*
831 * kernel = type 0
832 * client = type 1
833 */
834void 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
8bb8aefd 851 memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
f7be4ee0
MM
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
880out:
881gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
882
883 return;
884
885}
886
887void 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))
54804949 892 goto out;
f7be4ee0
MM
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))
8bb8aefd 897 < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
f7be4ee0
MM
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__);
8bb8aefd 903 strcpy(kernel_debug_string, ORANGEFS_ALL);
f7be4ee0
MM
904 goto out;
905 }
906 }
907
908out:
909
910 return;
911}
912
913void 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)
8bb8aefd 924 < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
f7be4ee0
MM
925 strcat(client_debug_string,
926 cdm_array[index].keyword);
927 strcat(client_debug_string, ",");
928 } else {
929 gossip_err("%s: overflow!\n", __func__);
8bb8aefd 930 strcpy(client_debug_string, ORANGEFS_ALL);
f7be4ee0
MM
931 goto out;
932 }
933 }
934out:
935 return;
936}
937
938int keyword_is_amalgam(char *keyword)
939{
940 int rc = 0;
941
8bb8aefd 942 if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
f7be4ee0
MM
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 */
954int 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)) {
8bb8aefd 966 strcpy(client_debug_string, ORANGEFS_ALL);
f7be4ee0
MM
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)) {
8bb8aefd 973 strcpy(client_debug_string, ORANGEFS_VERBOSE);
f7be4ee0
MM
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) {
8bb8aefd 982 strcpy(kernel_debug_string, ORANGEFS_ALL);
f7be4ee0
MM
983 rc = 1;
984 goto out;
985 }
986 }
987
988out:
989
990 return rc;
991}
992
993/*
994 * kernel = type 0
995 * client = type 1
996 */
997void 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);
eeaa3d44 1002 char *original_pointer;
f7be4ee0
MM
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
eeaa3d44 1018 original_pointer = strsep_fodder;
f7be4ee0
MM
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
eeaa3d44 1032 kfree(original_pointer);
f7be4ee0
MM
1033}
1034
1035void 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
1046void 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}
This page took 0.077486 seconds and 5 git commands to generate.