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