Merge remote-tracking branch 'omap_dss2/for-next'
[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;
6eaff8c7 53 case ORANGEFS_VFS_OP_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) {
78fee0b6 156 attrs->owner = from_kuid(&init_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) {
78fee0b6 161 attrs->group = from_kgid(&init_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
26662633
MB
231static 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
71680c18 254int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
3c9cf98d
MB
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;
26662633 259 int ret, type;
3c9cf98d
MB
260
261 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
262 get_khandle_from_ino(inode));
263
71680c18 264 if (!new && !bypass) {
8bbb20a8 265 if (time_before(jiffies, orangefs_inode->getattr_time))
71680c18
MB
266 return 0;
267 }
268
3c9cf98d
MB
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;
71680c18 273 new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
3c9cf98d
MB
274
275 ret = service_operation(new_op, __func__,
276 get_interruptible_flag(inode));
277 if (ret != 0)
278 goto out;
279
26662633 280 type = orangefs_inode_type(new_op->
3c9cf98d 281 downcall.resp.getattr.attributes.objtype);
26662633
MB
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;
3c9cf98d
MB
288 }
289
26662633 290 switch (type) {
3c9cf98d
MB
291 case S_IFREG:
292 inode->i_flags = orangefs_inode_flags(&new_op->
293 downcall.resp.getattr.attributes);
71680c18
MB
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);
3c9cf98d
MB
306 break;
307 case S_IFDIR:
09cbfeaf 308 inode->i_size = PAGE_SIZE;
3c9cf98d
MB
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);
2eacea74 320 ret = strscpy(orangefs_inode->link_target,
3c9cf98d
MB
321 new_op->downcall.resp.getattr.link_target,
322 ORANGEFS_NAME_MAX);
2eacea74
MB
323 if (ret == -E2BIG) {
324 ret = -EIO;
325 goto out;
326 }
e8da254c 327 inode->i_link = orangefs_inode->link_target;
3c9cf98d
MB
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 */
26662633 347 inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
3c9cf98d
MB
348 orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
349
4cd8f319 350 orangefs_inode->getattr_time = jiffies + getattr_timeout_msecs*HZ/1000;
3c9cf98d
MB
351 ret = 0;
352out:
353 op_release(new_op);
354 return ret;
355}
356
5859d77e
MB
357int 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
26662633
MB
378 ret = orangefs_inode_is_stale(inode, 0,
379 &new_op->downcall.resp.getattr.attributes,
380 new_op->downcall.resp.getattr.link_target);
5859d77e
MB
381out:
382 op_release(new_op);
383 return ret;
384}
385
f7be4ee0 386/*
8bb8aefd 387 * issues a orangefs setattr request to make sure the new attribute values
f7be4ee0
MM
388 * take effect if successful. returns 0 on success; -errno otherwise
389 */
8bb8aefd 390int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
f7be4ee0 391{
8bb8aefd
YL
392 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
393 struct orangefs_kernel_op_s *new_op;
f7be4ee0
MM
394 int ret;
395
8bb8aefd 396 new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
f7be4ee0
MM
397 if (!new_op)
398 return -ENOMEM;
399
8bb8aefd 400 new_op->upcall.req.setattr.refn = orangefs_inode->refn;
f7be4ee0
MM
401 ret = copy_attributes_from_inode(inode,
402 &new_op->upcall.req.setattr.attributes,
403 iattr);
ed42fe05
AV
404 if (ret >= 0) {
405 ret = service_operation(new_op, __func__,
f7be4ee0
MM
406 get_interruptible_flag(inode));
407
ed42fe05
AV
408 gossip_debug(GOSSIP_UTILS_DEBUG,
409 "orangefs_inode_setattr: returning %d\n",
410 ret);
411 }
f7be4ee0 412
f7be4ee0
MM
413 op_release(new_op);
414
415 /*
416 * successful setattr should clear the atime, mtime and
417 * ctime flags.
418 */
419 if (ret == 0) {
8bb8aefd
YL
420 ClearAtimeFlag(orangefs_inode);
421 ClearMtimeFlag(orangefs_inode);
422 ClearCtimeFlag(orangefs_inode);
423 ClearModeFlag(orangefs_inode);
8bbb20a8 424 orangefs_inode->getattr_time = jiffies - 1;
f7be4ee0
MM
425 }
426
427 return ret;
428}
429
8bb8aefd 430int orangefs_flush_inode(struct inode *inode)
f7be4ee0
MM
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;
8bb8aefd 444 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
f7be4ee0
MM
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 */
8bb8aefd
YL
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);
f7be4ee0
MM
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,
8bb8aefd 482 "*********** orangefs_flush_inode: %pU "
f7be4ee0
MM
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,
8bb8aefd 488 "orangefs_flush_inode skipping setattr()\n");
f7be4ee0
MM
489 return 0;
490 }
491
492 gossip_debug(GOSSIP_UTILS_DEBUG,
8bb8aefd 493 "orangefs_flush_inode (%pU) writing mode %o\n",
f7be4ee0
MM
494 get_khandle_from_ino(inode),
495 inode->i_mode);
496
8bb8aefd 497 ret = orangefs_inode_setattr(inode, &wbattr);
f7be4ee0
MM
498
499 return ret;
500}
501
8bb8aefd 502int orangefs_unmount_sb(struct super_block *sb)
f7be4ee0
MM
503{
504 int ret = -EINVAL;
8bb8aefd 505 struct orangefs_kernel_op_s *new_op = NULL;
f7be4ee0
MM
506
507 gossip_debug(GOSSIP_UTILS_DEBUG,
8bb8aefd 508 "orangefs_unmount_sb called on sb %p\n",
f7be4ee0
MM
509 sb);
510
8bb8aefd 511 new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
f7be4ee0
MM
512 if (!new_op)
513 return -ENOMEM;
8bb8aefd
YL
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);
f7be4ee0
MM
519
520 gossip_debug(GOSSIP_UTILS_DEBUG,
8bb8aefd
YL
521 "Attempting ORANGEFS Unmount via host %s\n",
522 new_op->upcall.req.fs_umount.orangefs_config_server);
f7be4ee0 523
8bb8aefd 524 ret = service_operation(new_op, "orangefs_fs_umount", 0);
f7be4ee0
MM
525
526 gossip_debug(GOSSIP_UTILS_DEBUG,
8bb8aefd 527 "orangefs_unmount: got return value of %d\n", ret);
f7be4ee0
MM
528 if (ret)
529 sb = ERR_PTR(ret);
530 else
8bb8aefd 531 ORANGEFS_SB(sb)->mount_pending = 1;
f7be4ee0
MM
532
533 op_release(new_op);
534 return ret;
535}
536
8bb8aefd 537void orangefs_make_bad_inode(struct inode *inode)
f7be4ee0
MM
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
54804949
MM
556/*
557 * The following is a very dirty hack that is now a permanent part of the
8bb8aefd 558 * ORANGEFS protocol. See protocol.h for more error definitions.
54804949 559 */
894ac432 560
8bb8aefd 561/* The order matches include/orangefs-types.h in the OrangeFS source. */
894ac432 562static int PINT_errno_mapping[] = {
54804949
MM
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
894ac432 573};
f7be4ee0 574
8bb8aefd 575int orangefs_normalize_to_errno(__s32 error_code)
f7be4ee0 576{
54804949
MM
577 __u32 i;
578
894ac432
MB
579 /* Success */
580 if (error_code == 0) {
581 return 0;
54804949
MM
582 /*
583 * This shouldn't ever happen. If it does it should be fixed on the
584 * server.
585 */
894ac432 586 } else if (error_code > 0) {
8bb8aefd
YL
587 gossip_err("orangefs: error status receieved.\n");
588 gossip_err("orangefs: assuming error code is inverted.\n");
f7be4ee0
MM
589 error_code = -error_code;
590 }
591
54804949 592 /*
8bb8aefd 593 * XXX: This is very bad since error codes from ORANGEFS may not be
54804949
MM
594 * suitable for return into userspace.
595 */
894ac432 596
54804949 597 /*
8bb8aefd 598 * Convert ORANGEFS error values into errno values suitable for return
54804949
MM
599 * from the kernel.
600 */
8bb8aefd 601 if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
894ac432 602 if (((-error_code) &
8bb8aefd
YL
603 (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
604 ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
f7be4ee0
MM
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 */
8bb8aefd 612 gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
f7be4ee0
MM
613 error_code = -EINVAL;
614 }
894ac432 615
8bb8aefd
YL
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);
54804949 619 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
894ac432
MB
620 error_code = -PINT_errno_mapping[i];
621 else
622 error_code = -EINVAL;
623
54804949 624 /*
8bb8aefd 625 * Only ORANGEFS protocol error codes should ever come here. Otherwise
54804949
MM
626 * there is a bug somewhere.
627 */
894ac432 628 } else {
8bb8aefd 629 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
f7be4ee0
MM
630 }
631 return error_code;
632}
633
634#define NUM_MODES 11
8bb8aefd 635__s32 ORANGEFS_util_translate_mode(int mode)
f7be4ee0
MM
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 };
8bb8aefd
YL
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
f7be4ee0
MM
650 };
651
652 for (i = 0; i < NUM_MODES; i++)
653 if (mode & modes[i])
8bb8aefd 654 ret |= orangefs_modes[i];
f7be4ee0
MM
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 */
665int 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
8bb8aefd 716 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
f7be4ee0
MM
717 client_verbose_index = i;
718
8bb8aefd 719 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
f7be4ee0
MM
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
729out:
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 */
750int 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
828out:
829
830 return rc;
831
832}
833
834/*
835 * kernel = type 0
836 * client = type 1
837 */
838void 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
8bb8aefd 855 memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
f7be4ee0
MM
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
884out:
885gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
886
887 return;
888
889}
890
891void 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))
54804949 896 goto out;
f7be4ee0
MM
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))
8bb8aefd 901 < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
f7be4ee0
MM
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__);
8bb8aefd 907 strcpy(kernel_debug_string, ORANGEFS_ALL);
f7be4ee0
MM
908 goto out;
909 }
910 }
911
912out:
913
914 return;
915}
916
917void 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)
8bb8aefd 928 < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
f7be4ee0
MM
929 strcat(client_debug_string,
930 cdm_array[index].keyword);
931 strcat(client_debug_string, ",");
932 } else {
933 gossip_err("%s: overflow!\n", __func__);
8bb8aefd 934 strcpy(client_debug_string, ORANGEFS_ALL);
f7be4ee0
MM
935 goto out;
936 }
937 }
938out:
939 return;
940}
941
942int keyword_is_amalgam(char *keyword)
943{
944 int rc = 0;
945
8bb8aefd 946 if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
f7be4ee0
MM
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 */
958int 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)) {
8bb8aefd 970 strcpy(client_debug_string, ORANGEFS_ALL);
f7be4ee0
MM
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)) {
8bb8aefd 977 strcpy(client_debug_string, ORANGEFS_VERBOSE);
f7be4ee0
MM
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) {
8bb8aefd 986 strcpy(kernel_debug_string, ORANGEFS_ALL);
f7be4ee0
MM
987 rc = 1;
988 goto out;
989 }
990 }
991
992out:
993
994 return rc;
995}
996
997/*
998 * kernel = type 0
999 * client = type 1
1000 */
1001void 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);
eeaa3d44 1006 char *original_pointer;
f7be4ee0
MM
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
eeaa3d44 1022 original_pointer = strsep_fodder;
f7be4ee0
MM
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
eeaa3d44 1036 kfree(original_pointer);
f7be4ee0
MM
1037}
1038
1039void 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
1050void 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}
This page took 0.097286 seconds and 5 git commands to generate.