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