blob: 8ef9e9646748e945046f13a1b9ff869c38cbeb40 [file] [log] [blame]
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001/*
2 * (C) 2001 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6#include "protocol.h"
Mike Marshall575e9462015-12-04 12:56:14 -05007#include "orangefs-kernel.h"
8#include "orangefs-dev-proto.h"
9#include "orangefs-bufmap.h"
Mike Marshallf7be4ee2015-07-17 10:38:14 -040010
Yi Liu8bb8aef2015-11-24 15:12:14 -050011__s32 fsid_of_op(struct orangefs_kernel_op_s *op)
Mike Marshallf7be4ee2015-07-17 10:38:14 -040012{
Yi Liu8bb8aef2015-11-24 15:12:14 -050013 __s32 fsid = ORANGEFS_FS_ID_NULL;
Mike Marshallf7be4ee2015-07-17 10:38:14 -040014
15 if (op) {
16 switch (op->upcall.type) {
Yi Liu8bb8aef2015-11-24 15:12:14 -050017 case ORANGEFS_VFS_OP_FILE_IO:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040018 fsid = op->upcall.req.io.refn.fs_id;
19 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050020 case ORANGEFS_VFS_OP_LOOKUP:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040021 fsid = op->upcall.req.lookup.parent_refn.fs_id;
22 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050023 case ORANGEFS_VFS_OP_CREATE:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040024 fsid = op->upcall.req.create.parent_refn.fs_id;
25 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050026 case ORANGEFS_VFS_OP_GETATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040027 fsid = op->upcall.req.getattr.refn.fs_id;
28 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050029 case ORANGEFS_VFS_OP_REMOVE:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040030 fsid = op->upcall.req.remove.parent_refn.fs_id;
31 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050032 case ORANGEFS_VFS_OP_MKDIR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040033 fsid = op->upcall.req.mkdir.parent_refn.fs_id;
34 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050035 case ORANGEFS_VFS_OP_READDIR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040036 fsid = op->upcall.req.readdir.refn.fs_id;
37 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050038 case ORANGEFS_VFS_OP_SETATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040039 fsid = op->upcall.req.setattr.refn.fs_id;
40 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050041 case ORANGEFS_VFS_OP_SYMLINK:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040042 fsid = op->upcall.req.sym.parent_refn.fs_id;
43 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050044 case ORANGEFS_VFS_OP_RENAME:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040045 fsid = op->upcall.req.rename.old_parent_refn.fs_id;
46 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050047 case ORANGEFS_VFS_OP_STATFS:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040048 fsid = op->upcall.req.statfs.fs_id;
49 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050050 case ORANGEFS_VFS_OP_TRUNCATE:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040051 fsid = op->upcall.req.truncate.refn.fs_id;
52 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050053 case ORANGEFS_VFS_OP_MMAP_RA_FLUSH:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040054 fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
55 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050056 case ORANGEFS_VFS_OP_FS_UMOUNT:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040057 fsid = op->upcall.req.fs_umount.fs_id;
58 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050059 case ORANGEFS_VFS_OP_GETXATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040060 fsid = op->upcall.req.getxattr.refn.fs_id;
61 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050062 case ORANGEFS_VFS_OP_SETXATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040063 fsid = op->upcall.req.setxattr.refn.fs_id;
64 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050065 case ORANGEFS_VFS_OP_LISTXATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040066 fsid = op->upcall.req.listxattr.refn.fs_id;
67 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050068 case ORANGEFS_VFS_OP_REMOVEXATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040069 fsid = op->upcall.req.removexattr.refn.fs_id;
70 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050071 case ORANGEFS_VFS_OP_FSYNC:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040072 fsid = op->upcall.req.fsync.refn.fs_id;
73 break;
74 default:
75 break;
76 }
77 }
78 return fsid;
79}
80
Martin Brandenburg394f6472016-01-25 15:33:39 -050081static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
Mike Marshallf7be4ee2015-07-17 10:38:14 -040082{
Martin Brandenburg394f6472016-01-25 15:33:39 -050083 int flags = 0;
Yi Liu8bb8aef2015-11-24 15:12:14 -050084 if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
Martin Brandenburg394f6472016-01-25 15:33:39 -050085 flags |= S_IMMUTABLE;
Mike Marshallf7be4ee2015-07-17 10:38:14 -040086 else
Martin Brandenburg394f6472016-01-25 15:33:39 -050087 flags &= ~S_IMMUTABLE;
Yi Liu8bb8aef2015-11-24 15:12:14 -050088 if (attrs->flags & ORANGEFS_APPEND_FL)
Martin Brandenburg394f6472016-01-25 15:33:39 -050089 flags |= S_APPEND;
Mike Marshallf7be4ee2015-07-17 10:38:14 -040090 else
Martin Brandenburg394f6472016-01-25 15:33:39 -050091 flags &= ~S_APPEND;
Yi Liu8bb8aef2015-11-24 15:12:14 -050092 if (attrs->flags & ORANGEFS_NOATIME_FL)
Martin Brandenburg394f6472016-01-25 15:33:39 -050093 flags |= S_NOATIME;
Mike Marshallf7be4ee2015-07-17 10:38:14 -040094 else
Martin Brandenburg394f6472016-01-25 15:33:39 -050095 flags &= ~S_NOATIME;
96 return flags;
97}
Mike Marshallf7be4ee2015-07-17 10:38:14 -040098
Martin Brandenburg394f6472016-01-25 15:33:39 -050099static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
100{
101 int perm_mode = 0;
102
103 if (attrs->perms & ORANGEFS_O_EXECUTE)
104 perm_mode |= S_IXOTH;
105 if (attrs->perms & ORANGEFS_O_WRITE)
106 perm_mode |= S_IWOTH;
107 if (attrs->perms & ORANGEFS_O_READ)
108 perm_mode |= S_IROTH;
109
110 if (attrs->perms & ORANGEFS_G_EXECUTE)
111 perm_mode |= S_IXGRP;
112 if (attrs->perms & ORANGEFS_G_WRITE)
113 perm_mode |= S_IWGRP;
114 if (attrs->perms & ORANGEFS_G_READ)
115 perm_mode |= S_IRGRP;
116
117 if (attrs->perms & ORANGEFS_U_EXECUTE)
118 perm_mode |= S_IXUSR;
119 if (attrs->perms & ORANGEFS_U_WRITE)
120 perm_mode |= S_IWUSR;
121 if (attrs->perms & ORANGEFS_U_READ)
122 perm_mode |= S_IRUSR;
123
124 if (attrs->perms & ORANGEFS_G_SGID)
125 perm_mode |= S_ISGID;
126 if (attrs->perms & ORANGEFS_U_SUID)
127 perm_mode |= S_ISUID;
128
129 return perm_mode;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400130}
131
132/* NOTE: symname is ignored unless the inode is a sym link */
133static int copy_attributes_to_inode(struct inode *inode,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500134 struct ORANGEFS_sys_attr_s *attrs,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400135 char *symname)
136{
137 int ret = -1;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500138 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400139 loff_t inode_size = 0;
140 loff_t rounded_up_size = 0;
141
142
143 /*
Mike Marshall54804942015-10-05 13:44:24 -0400144 * 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.
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400156 */
157 gossip_debug(GOSSIP_UTILS_DEBUG,
158 "attrs->mask = %x (objtype = %s)\n",
159 attrs->mask,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500160 attrs->objtype == ORANGEFS_TYPE_METAFILE ? "file" :
161 attrs->objtype == ORANGEFS_TYPE_DIRECTORY ? "directory" :
162 attrs->objtype == ORANGEFS_TYPE_SYMLINK ? "symlink" :
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400163 "invalid/unknown");
164
165 switch (attrs->objtype) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500166 case ORANGEFS_TYPE_METAFILE:
Martin Brandenburg394f6472016-01-25 15:33:39 -0500167 inode->i_flags = orangefs_inode_flags(attrs);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500168 if (attrs->mask & ORANGEFS_ATTR_SYS_SIZE) {
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400169 inode_size = (loff_t) attrs->size;
170 rounded_up_size =
171 (inode_size + (4096 - (inode_size % 4096)));
172
Yi Liu8bb8aef2015-11-24 15:12:14 -0500173 orangefs_lock_inode(inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400174 inode->i_bytes = inode_size;
175 inode->i_blocks =
176 (unsigned long)(rounded_up_size / 512);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500177 orangefs_unlock_inode(inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400178
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;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500188 case ORANGEFS_TYPE_SYMLINK:
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400189 if (symname != NULL) {
190 inode->i_size = (loff_t) strlen(symname);
191 break;
192 }
193 /*FALLTHRU*/
194 default:
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400195 inode->i_size = PAGE_CACHE_SIZE;
Mike Marshallf0566532015-08-05 13:46:28 -0400196
Yi Liu8bb8aef2015-11-24 15:12:14 -0500197 orangefs_lock_inode(inode);
Mike Marshallf0566532015-08-05 13:46:28 -0400198 inode_set_bytes(inode, inode->i_size);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500199 orangefs_unlock_inode(inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400200 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);
Arnd Bergmannbe81ce42016-02-26 13:54:10 +0100205 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;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400208 inode->i_atime.tv_nsec = 0;
209 inode->i_mtime.tv_nsec = 0;
210 inode->i_ctime.tv_nsec = 0;
211
Martin Brandenburg394f6472016-01-25 15:33:39 -0500212 inode->i_mode = orangefs_inode_perms(attrs);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400213
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) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500223 case ORANGEFS_TYPE_METAFILE:
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400224 inode->i_mode |= S_IFREG;
225 ret = 0;
226 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500227 case ORANGEFS_TYPE_DIRECTORY:
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400228 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;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500237 case ORANGEFS_TYPE_SYMLINK:
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400238 inode->i_mode |= S_IFLNK;
239
240 /* copy link target to inode private data */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500241 if (orangefs_inode && symname) {
242 strncpy(orangefs_inode->link_target,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400243 symname,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500244 ORANGEFS_NAME_MAX);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400245 gossip_debug(GOSSIP_UTILS_DEBUG,
246 "Copied attr link target %s\n",
Yi Liu8bb8aef2015-11-24 15:12:14 -0500247 orangefs_inode->link_target);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400248 }
249 gossip_debug(GOSSIP_UTILS_DEBUG,
250 "symlink mode %o\n",
251 inode->i_mode);
252 ret = 0;
253 break;
254 default:
Yi Liu8bb8aef2015-11-24 15:12:14 -0500255 gossip_err("orangefs: copy_attributes_to_inode: got invalid attribute type %x\n",
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400256 attrs->objtype);
257 }
258
259 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500260 "orangefs: copy_attributes_to_inode: setting i_mode to %o, i_size to %lu\n",
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400261 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,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500272 struct ORANGEFS_sys_attr_s *attrs,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400273 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);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500292 attrs->mask |= ORANGEFS_ATTR_SYS_UID;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400293 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);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500297 attrs->mask |= ORANGEFS_ATTR_SYS_GID;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400298 gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
299 }
300
301 if (iattr->ia_valid & ATTR_ATIME) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500302 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400303 if (iattr->ia_valid & ATTR_ATIME_SET) {
Arnd Bergmannbe81ce42016-02-26 13:54:10 +0100304 attrs->atime = (time64_t)iattr->ia_atime.tv_sec;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500305 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400306 }
307 }
308 if (iattr->ia_valid & ATTR_MTIME) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500309 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400310 if (iattr->ia_valid & ATTR_MTIME_SET) {
Arnd Bergmannbe81ce42016-02-26 13:54:10 +0100311 attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500312 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400313 }
314 }
315 if (iattr->ia_valid & ATTR_CTIME)
Yi Liu8bb8aef2015-11-24 15:12:14 -0500316 attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400317
318 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500319 * ORANGEFS cannot set size with a setattr operation. Probably not likely
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400320 * 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
Yi Liu8bb8aef2015-11-24 15:12:14 -0500347 attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
348 attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400349 }
350
351 return 0;
352}
353
Martin Brandenburg99109822016-01-28 10:19:40 -0500354static int compare_attributes_to_inode(struct inode *inode,
355 struct ORANGEFS_sys_attr_s *attrs,
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500356 char *symname,
357 int mask)
Martin Brandenburg99109822016-01-28 10:19:40 -0500358{
359 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
360 loff_t inode_size, rounded_up_size;
361
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500362 /* 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
Martin Brandenburg99109822016-01-28 10:19:40 -0500370 /* Compare file size. */
371
372 switch (attrs->objtype) {
373 case ORANGEFS_TYPE_METAFILE:
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500374 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 }
Martin Brandenburg99109822016-01-28 10:19:40 -0500382 break;
383 case ORANGEFS_TYPE_SYMLINK:
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500384 if (mask & ORANGEFS_ATTR_SYS_SIZE)
385 if (symname && strlen(symname) != inode->i_size)
386 return 0;
Martin Brandenburg99109822016-01-28 10:19:40 -0500387 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
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500396 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 ||
Martin Brandenburg99109822016-01-28 10:19:40 -0500412 inode->i_mtime.tv_nsec != 0 ||
413 inode->i_ctime.tv_nsec != 0)
414 return 0;
415
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500416 if (mask & ORANGEFS_ATTR_SYS_PERM &&
417 (inode->i_mode & ~(S_ISVTX|S_IFREG|S_IFDIR|S_IFLNK)) !=
Martin Brandenburg99109822016-01-28 10:19:40 -0500418 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:
Martin Brandenburgcf22644a2016-02-05 16:37:00 -0500429 if (!S_ISREG(inode->i_mode))
Martin Brandenburg99109822016-01-28 10:19:40 -0500430 return 0;
431 break;
432 case ORANGEFS_TYPE_DIRECTORY:
Martin Brandenburgcf22644a2016-02-05 16:37:00 -0500433 if (!S_ISDIR(inode->i_mode))
Martin Brandenburg99109822016-01-28 10:19:40 -0500434 return 0;
435 if (inode->i_nlink != 1)
436 return 0;
437 break;
438 case ORANGEFS_TYPE_SYMLINK:
Martin Brandenburgcf22644a2016-02-05 16:37:00 -0500439 if (!S_ISLNK(inode->i_mode))
Martin Brandenburg99109822016-01-28 10:19:40 -0500440 return 0;
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500441 if (orangefs_inode && symname &&
442 mask & ORANGEFS_ATTR_SYS_LNK_TARGET)
Martin Brandenburg99109822016-01-28 10:19:40 -0500443 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
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400455/*
Martin Brandenburg99109822016-01-28 10:19:40 -0500456 * 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.
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400460 */
Martin Brandenburg99109822016-01-28 10:19:40 -0500461int orangefs_inode_getattr(struct inode *inode, __u32 getattr_mask, int check)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400462{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500463 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
464 struct orangefs_kernel_op_s *new_op;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400465 int ret = -EINVAL;
466
467 gossip_debug(GOSSIP_UTILS_DEBUG,
468 "%s: called on inode %pU\n",
469 __func__,
470 get_khandle_from_ino(inode));
471
Yi Liu8bb8aef2015-11-24 15:12:14 -0500472 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400473 if (!new_op)
474 return -ENOMEM;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500475 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400476 new_op->upcall.req.getattr.mask = getattr_mask;
477
478 ret = service_operation(new_op, __func__,
479 get_interruptible_flag(inode));
480 if (ret != 0)
481 goto out;
482
Martin Brandenburg99109822016-01-28 10:19:40 -0500483 if (check) {
484 ret = compare_attributes_to_inode(inode,
485 &new_op->downcall.resp.getattr.attributes,
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500486 new_op->downcall.resp.getattr.link_target,
487 getattr_mask);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400488
Martin Brandenburg99109822016-01-28 10:19:40 -0500489 if (new_op->downcall.resp.getattr.attributes.objtype ==
490 ORANGEFS_TYPE_METAFILE) {
491 if (orangefs_inode->blksize !=
492 new_op->downcall.resp.getattr.attributes.blksize)
493 ret = 0;
494 } else {
495 if (orangefs_inode->blksize != 1 << inode->i_blkbits)
496 ret = 0;
497 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400498 } else {
Martin Brandenburg99109822016-01-28 10:19:40 -0500499 if (copy_attributes_to_inode(inode,
500 &new_op->downcall.resp.getattr.attributes,
501 new_op->downcall.resp.getattr.link_target)) {
502 gossip_err("%s: failed to copy attributes\n", __func__);
503 ret = -ENOENT;
504 goto out;
505 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400506
Martin Brandenburg99109822016-01-28 10:19:40 -0500507 /*
508 * Store blksize in orangefs specific part of inode structure;
509 * we are only going to use this to report to stat to make sure
510 * it doesn't perturb any inode related code paths.
511 */
512 if (new_op->downcall.resp.getattr.attributes.objtype ==
513 ORANGEFS_TYPE_METAFILE) {
514 orangefs_inode->blksize = new_op->downcall.resp.
515 getattr.attributes.blksize;
516 } else {
517 /*
518 * mimic behavior of generic_fillattr() for other file
519 * types.
520 */
521 orangefs_inode->blksize = (1 << inode->i_blkbits);
522
523 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400524 }
525
526out:
527 gossip_debug(GOSSIP_UTILS_DEBUG,
528 "Getattr on handle %pU, "
529 "fsid %d\n (inode ct = %d) returned %d\n",
Yi Liu8bb8aef2015-11-24 15:12:14 -0500530 &orangefs_inode->refn.khandle,
531 orangefs_inode->refn.fs_id,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400532 (int)atomic_read(&inode->i_count),
533 ret);
534
535 op_release(new_op);
536 return ret;
537}
538
539/*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500540 * issues a orangefs setattr request to make sure the new attribute values
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400541 * take effect if successful. returns 0 on success; -errno otherwise
542 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500543int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400544{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500545 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
546 struct orangefs_kernel_op_s *new_op;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400547 int ret;
548
Yi Liu8bb8aef2015-11-24 15:12:14 -0500549 new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400550 if (!new_op)
551 return -ENOMEM;
552
Yi Liu8bb8aef2015-11-24 15:12:14 -0500553 new_op->upcall.req.setattr.refn = orangefs_inode->refn;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400554 ret = copy_attributes_from_inode(inode,
555 &new_op->upcall.req.setattr.attributes,
556 iattr);
Al Viroed42fe02016-01-22 19:47:47 -0500557 if (ret >= 0) {
558 ret = service_operation(new_op, __func__,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400559 get_interruptible_flag(inode));
560
Al Viroed42fe02016-01-22 19:47:47 -0500561 gossip_debug(GOSSIP_UTILS_DEBUG,
562 "orangefs_inode_setattr: returning %d\n",
563 ret);
564 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400565
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400566 op_release(new_op);
567
568 /*
569 * successful setattr should clear the atime, mtime and
570 * ctime flags.
571 */
572 if (ret == 0) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500573 ClearAtimeFlag(orangefs_inode);
574 ClearMtimeFlag(orangefs_inode);
575 ClearCtimeFlag(orangefs_inode);
576 ClearModeFlag(orangefs_inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400577 }
578
579 return ret;
580}
581
Yi Liu8bb8aef2015-11-24 15:12:14 -0500582int orangefs_flush_inode(struct inode *inode)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400583{
584 /*
585 * If it is a dirty inode, this function gets called.
586 * Gather all the information that needs to be setattr'ed
587 * Right now, this will only be used for mode, atime, mtime
588 * and/or ctime.
589 */
590 struct iattr wbattr;
591 int ret;
592 int mtime_flag;
593 int ctime_flag;
594 int atime_flag;
595 int mode_flag;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500596 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400597
598 memset(&wbattr, 0, sizeof(wbattr));
599
600 /*
601 * check inode flags up front, and clear them if they are set. This
602 * will prevent multiple processes from all trying to flush the same
603 * inode if they call close() simultaneously
604 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500605 mtime_flag = MtimeFlag(orangefs_inode);
606 ClearMtimeFlag(orangefs_inode);
607 ctime_flag = CtimeFlag(orangefs_inode);
608 ClearCtimeFlag(orangefs_inode);
609 atime_flag = AtimeFlag(orangefs_inode);
610 ClearAtimeFlag(orangefs_inode);
611 mode_flag = ModeFlag(orangefs_inode);
612 ClearModeFlag(orangefs_inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400613
614 /* -- Lazy atime,mtime and ctime update --
615 * Note: all times are dictated by server in the new scheme
616 * and not by the clients
617 *
618 * Also mode updates are being handled now..
619 */
620
621 if (mtime_flag)
622 wbattr.ia_valid |= ATTR_MTIME;
623 if (ctime_flag)
624 wbattr.ia_valid |= ATTR_CTIME;
625 if (atime_flag)
626 wbattr.ia_valid |= ATTR_ATIME;
627
628 if (mode_flag) {
629 wbattr.ia_mode = inode->i_mode;
630 wbattr.ia_valid |= ATTR_MODE;
631 }
632
633 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500634 "*********** orangefs_flush_inode: %pU "
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400635 "(ia_valid %d)\n",
636 get_khandle_from_ino(inode),
637 wbattr.ia_valid);
638 if (wbattr.ia_valid == 0) {
639 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500640 "orangefs_flush_inode skipping setattr()\n");
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400641 return 0;
642 }
643
644 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500645 "orangefs_flush_inode (%pU) writing mode %o\n",
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400646 get_khandle_from_ino(inode),
647 inode->i_mode);
648
Yi Liu8bb8aef2015-11-24 15:12:14 -0500649 ret = orangefs_inode_setattr(inode, &wbattr);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400650
651 return ret;
652}
653
Yi Liu8bb8aef2015-11-24 15:12:14 -0500654int orangefs_unmount_sb(struct super_block *sb)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400655{
656 int ret = -EINVAL;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500657 struct orangefs_kernel_op_s *new_op = NULL;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400658
659 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500660 "orangefs_unmount_sb called on sb %p\n",
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400661 sb);
662
Yi Liu8bb8aef2015-11-24 15:12:14 -0500663 new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400664 if (!new_op)
665 return -ENOMEM;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500666 new_op->upcall.req.fs_umount.id = ORANGEFS_SB(sb)->id;
667 new_op->upcall.req.fs_umount.fs_id = ORANGEFS_SB(sb)->fs_id;
668 strncpy(new_op->upcall.req.fs_umount.orangefs_config_server,
669 ORANGEFS_SB(sb)->devname,
670 ORANGEFS_MAX_SERVER_ADDR_LEN);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400671
672 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500673 "Attempting ORANGEFS Unmount via host %s\n",
674 new_op->upcall.req.fs_umount.orangefs_config_server);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400675
Yi Liu8bb8aef2015-11-24 15:12:14 -0500676 ret = service_operation(new_op, "orangefs_fs_umount", 0);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400677
678 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500679 "orangefs_unmount: got return value of %d\n", ret);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400680 if (ret)
681 sb = ERR_PTR(ret);
682 else
Yi Liu8bb8aef2015-11-24 15:12:14 -0500683 ORANGEFS_SB(sb)->mount_pending = 1;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400684
685 op_release(new_op);
686 return ret;
687}
688
Yi Liu8bb8aef2015-11-24 15:12:14 -0500689void orangefs_make_bad_inode(struct inode *inode)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400690{
691 if (is_root_handle(inode)) {
692 /*
693 * if this occurs, the pvfs2-client-core was killed but we
694 * can't afford to lose the inode operations and such
695 * associated with the root handle in any case.
696 */
697 gossip_debug(GOSSIP_UTILS_DEBUG,
698 "*** NOT making bad root inode %pU\n",
699 get_khandle_from_ino(inode));
700 } else {
701 gossip_debug(GOSSIP_UTILS_DEBUG,
702 "*** making bad inode %pU\n",
703 get_khandle_from_ino(inode));
704 make_bad_inode(inode);
705 }
706}
707
Mike Marshall54804942015-10-05 13:44:24 -0400708/*
709 * The following is a very dirty hack that is now a permanent part of the
Yi Liu8bb8aef2015-11-24 15:12:14 -0500710 * ORANGEFS protocol. See protocol.h for more error definitions.
Mike Marshall54804942015-10-05 13:44:24 -0400711 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400712
Yi Liu8bb8aef2015-11-24 15:12:14 -0500713/* The order matches include/orangefs-types.h in the OrangeFS source. */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400714static int PINT_errno_mapping[] = {
Mike Marshall54804942015-10-05 13:44:24 -0400715 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
716 EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
717 EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
718 ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
719 EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
720 EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
721 ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
722 EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
723 ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
724 EACCES, ECONNRESET, ERANGE
Martin Brandenburg894ac432015-10-02 12:11:19 -0400725};
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400726
Yi Liu8bb8aef2015-11-24 15:12:14 -0500727int orangefs_normalize_to_errno(__s32 error_code)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400728{
Mike Marshall54804942015-10-05 13:44:24 -0400729 __u32 i;
730
Martin Brandenburg894ac432015-10-02 12:11:19 -0400731 /* Success */
732 if (error_code == 0) {
733 return 0;
Mike Marshall54804942015-10-05 13:44:24 -0400734 /*
735 * This shouldn't ever happen. If it does it should be fixed on the
736 * server.
737 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400738 } else if (error_code > 0) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500739 gossip_err("orangefs: error status receieved.\n");
740 gossip_err("orangefs: assuming error code is inverted.\n");
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400741 error_code = -error_code;
742 }
743
Mike Marshall54804942015-10-05 13:44:24 -0400744 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500745 * XXX: This is very bad since error codes from ORANGEFS may not be
Mike Marshall54804942015-10-05 13:44:24 -0400746 * suitable for return into userspace.
747 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400748
Mike Marshall54804942015-10-05 13:44:24 -0400749 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500750 * Convert ORANGEFS error values into errno values suitable for return
Mike Marshall54804942015-10-05 13:44:24 -0400751 * from the kernel.
752 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500753 if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
Martin Brandenburg894ac432015-10-02 12:11:19 -0400754 if (((-error_code) &
Yi Liu8bb8aef2015-11-24 15:12:14 -0500755 (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
756 ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400757 /*
758 * cancellation error codes generally correspond to
759 * a timeout from the client's perspective
760 */
761 error_code = -ETIMEDOUT;
762 } else {
763 /* assume a default error code */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500764 gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400765 error_code = -EINVAL;
766 }
Martin Brandenburg894ac432015-10-02 12:11:19 -0400767
Yi Liu8bb8aef2015-11-24 15:12:14 -0500768 /* Convert ORANGEFS encoded errno values into regular errno values. */
769 } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
770 i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
Mike Marshall54804942015-10-05 13:44:24 -0400771 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
Martin Brandenburg894ac432015-10-02 12:11:19 -0400772 error_code = -PINT_errno_mapping[i];
773 else
774 error_code = -EINVAL;
775
Mike Marshall54804942015-10-05 13:44:24 -0400776 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500777 * Only ORANGEFS protocol error codes should ever come here. Otherwise
Mike Marshall54804942015-10-05 13:44:24 -0400778 * there is a bug somewhere.
779 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400780 } else {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500781 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400782 }
783 return error_code;
784}
785
786#define NUM_MODES 11
Yi Liu8bb8aef2015-11-24 15:12:14 -0500787__s32 ORANGEFS_util_translate_mode(int mode)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400788{
789 int ret = 0;
790 int i = 0;
791 static int modes[NUM_MODES] = {
792 S_IXOTH, S_IWOTH, S_IROTH,
793 S_IXGRP, S_IWGRP, S_IRGRP,
794 S_IXUSR, S_IWUSR, S_IRUSR,
795 S_ISGID, S_ISUID
796 };
Yi Liu8bb8aef2015-11-24 15:12:14 -0500797 static int orangefs_modes[NUM_MODES] = {
798 ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
799 ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
800 ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
801 ORANGEFS_G_SGID, ORANGEFS_U_SUID
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400802 };
803
804 for (i = 0; i < NUM_MODES; i++)
805 if (mode & modes[i])
Yi Liu8bb8aef2015-11-24 15:12:14 -0500806 ret |= orangefs_modes[i];
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400807
808 return ret;
809}
810#undef NUM_MODES
811
812/*
813 * After obtaining a string representation of the client's debug
814 * keywords and their associated masks, this function is called to build an
815 * array of these values.
816 */
817int orangefs_prepare_cdm_array(char *debug_array_string)
818{
819 int i;
820 int rc = -EINVAL;
821 char *cds_head = NULL;
822 char *cds_delimiter = NULL;
823 int keyword_len = 0;
824
825 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
826
827 /*
828 * figure out how many elements the cdm_array needs.
829 */
830 for (i = 0; i < strlen(debug_array_string); i++)
831 if (debug_array_string[i] == '\n')
832 cdm_element_count++;
833
834 if (!cdm_element_count) {
835 pr_info("No elements in client debug array string!\n");
836 goto out;
837 }
838
839 cdm_array =
840 kzalloc(cdm_element_count * sizeof(struct client_debug_mask),
841 GFP_KERNEL);
842 if (!cdm_array) {
843 pr_info("malloc failed for cdm_array!\n");
844 rc = -ENOMEM;
845 goto out;
846 }
847
848 cds_head = debug_array_string;
849
850 for (i = 0; i < cdm_element_count; i++) {
851 cds_delimiter = strchr(cds_head, '\n');
852 *cds_delimiter = '\0';
853
854 keyword_len = strcspn(cds_head, " ");
855
856 cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);
857 if (!cdm_array[i].keyword) {
858 rc = -ENOMEM;
859 goto out;
860 }
861
862 sscanf(cds_head,
863 "%s %llx %llx",
864 cdm_array[i].keyword,
865 (unsigned long long *)&(cdm_array[i].mask1),
866 (unsigned long long *)&(cdm_array[i].mask2));
867
Yi Liu8bb8aef2015-11-24 15:12:14 -0500868 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400869 client_verbose_index = i;
870
Yi Liu8bb8aef2015-11-24 15:12:14 -0500871 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400872 client_all_index = i;
873
874 cds_head = cds_delimiter + 1;
875 }
876
877 rc = cdm_element_count;
878
879 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc);
880
881out:
882
883 return rc;
884
885}
886
887/*
888 * /sys/kernel/debug/orangefs/debug-help can be catted to
889 * see all the available kernel and client debug keywords.
890 *
891 * When the kernel boots, we have no idea what keywords the
892 * client supports, nor their associated masks.
893 *
894 * We pass through this function once at boot and stamp a
895 * boilerplate "we don't know" message for the client in the
896 * debug-help file. We pass through here again when the client
897 * starts and then we can fill out the debug-help file fully.
898 *
899 * The client might be restarted any number of times between
900 * reboots, we only build the debug-help file the first time.
901 */
902int orangefs_prepare_debugfs_help_string(int at_boot)
903{
904 int rc = -EINVAL;
905 int i;
906 int byte_count = 0;
907 char *client_title = "Client Debug Keywords:\n";
908 char *kernel_title = "Kernel Debug Keywords:\n";
909
910 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
911
912 if (at_boot) {
913 byte_count += strlen(HELP_STRING_UNINITIALIZED);
914 client_title = HELP_STRING_UNINITIALIZED;
915 } else {
916 /*
917 * fill the client keyword/mask array and remember
918 * how many elements there were.
919 */
920 cdm_element_count =
921 orangefs_prepare_cdm_array(client_debug_array_string);
922 if (cdm_element_count <= 0)
923 goto out;
924
925 /* Count the bytes destined for debug_help_string. */
926 byte_count += strlen(client_title);
927
928 for (i = 0; i < cdm_element_count; i++) {
929 byte_count += strlen(cdm_array[i].keyword + 2);
930 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
931 pr_info("%s: overflow 1!\n", __func__);
932 goto out;
933 }
934 }
935
936 gossip_debug(GOSSIP_UTILS_DEBUG,
937 "%s: cdm_element_count:%d:\n",
938 __func__,
939 cdm_element_count);
940 }
941
942 byte_count += strlen(kernel_title);
943 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
944 byte_count +=
945 strlen(s_kmod_keyword_mask_map[i].keyword + 2);
946 if (byte_count >= DEBUG_HELP_STRING_SIZE) {
947 pr_info("%s: overflow 2!\n", __func__);
948 goto out;
949 }
950 }
951
952 /* build debug_help_string. */
953 debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL);
954 if (!debug_help_string) {
955 rc = -ENOMEM;
956 goto out;
957 }
958
959 strcat(debug_help_string, client_title);
960
961 if (!at_boot) {
962 for (i = 0; i < cdm_element_count; i++) {
963 strcat(debug_help_string, "\t");
964 strcat(debug_help_string, cdm_array[i].keyword);
965 strcat(debug_help_string, "\n");
966 }
967 }
968
969 strcat(debug_help_string, "\n");
970 strcat(debug_help_string, kernel_title);
971
972 for (i = 0; i < num_kmod_keyword_mask_map; i++) {
973 strcat(debug_help_string, "\t");
974 strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword);
975 strcat(debug_help_string, "\n");
976 }
977
978 rc = 0;
979
980out:
981
982 return rc;
983
984}
985
986/*
987 * kernel = type 0
988 * client = type 1
989 */
990void debug_mask_to_string(void *mask, int type)
991{
992 int i;
993 int len = 0;
994 char *debug_string;
995 int element_count = 0;
996
997 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
998
999 if (type) {
1000 debug_string = client_debug_string;
1001 element_count = cdm_element_count;
1002 } else {
1003 debug_string = kernel_debug_string;
1004 element_count = num_kmod_keyword_mask_map;
1005 }
1006
Yi Liu8bb8aef2015-11-24 15:12:14 -05001007 memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001008
1009 /*
1010 * Some keywords, like "all" or "verbose", are amalgams of
1011 * numerous other keywords. Make a special check for those
1012 * before grinding through the whole mask only to find out
1013 * later...
1014 */
1015 if (check_amalgam_keyword(mask, type))
1016 goto out;
1017
1018 /* Build the debug string. */
1019 for (i = 0; i < element_count; i++)
1020 if (type)
1021 do_c_string(mask, i);
1022 else
1023 do_k_string(mask, i);
1024
1025 len = strlen(debug_string);
1026
1027 if ((len) && (type))
1028 client_debug_string[len - 1] = '\0';
1029 else if (len)
1030 kernel_debug_string[len - 1] = '\0';
1031 else if (type)
1032 strcpy(client_debug_string, "none");
1033 else
1034 strcpy(kernel_debug_string, "none");
1035
1036out:
1037gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string);
1038
1039 return;
1040
1041}
1042
1043void do_k_string(void *k_mask, int index)
1044{
1045 __u64 *mask = (__u64 *) k_mask;
1046
1047 if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword))
Mike Marshall54804942015-10-05 13:44:24 -04001048 goto out;
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001049
1050 if (*mask & s_kmod_keyword_mask_map[index].mask_val) {
1051 if ((strlen(kernel_debug_string) +
1052 strlen(s_kmod_keyword_mask_map[index].keyword))
Yi Liu8bb8aef2015-11-24 15:12:14 -05001053 < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001054 strcat(kernel_debug_string,
1055 s_kmod_keyword_mask_map[index].keyword);
1056 strcat(kernel_debug_string, ",");
1057 } else {
1058 gossip_err("%s: overflow!\n", __func__);
Yi Liu8bb8aef2015-11-24 15:12:14 -05001059 strcpy(kernel_debug_string, ORANGEFS_ALL);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001060 goto out;
1061 }
1062 }
1063
1064out:
1065
1066 return;
1067}
1068
1069void do_c_string(void *c_mask, int index)
1070{
1071 struct client_debug_mask *mask = (struct client_debug_mask *) c_mask;
1072
1073 if (keyword_is_amalgam(cdm_array[index].keyword))
1074 goto out;
1075
1076 if ((mask->mask1 & cdm_array[index].mask1) ||
1077 (mask->mask2 & cdm_array[index].mask2)) {
1078 if ((strlen(client_debug_string) +
1079 strlen(cdm_array[index].keyword) + 1)
Yi Liu8bb8aef2015-11-24 15:12:14 -05001080 < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001081 strcat(client_debug_string,
1082 cdm_array[index].keyword);
1083 strcat(client_debug_string, ",");
1084 } else {
1085 gossip_err("%s: overflow!\n", __func__);
Yi Liu8bb8aef2015-11-24 15:12:14 -05001086 strcpy(client_debug_string, ORANGEFS_ALL);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001087 goto out;
1088 }
1089 }
1090out:
1091 return;
1092}
1093
1094int keyword_is_amalgam(char *keyword)
1095{
1096 int rc = 0;
1097
Yi Liu8bb8aef2015-11-24 15:12:14 -05001098 if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001099 rc = 1;
1100
1101 return rc;
1102}
1103
1104/*
1105 * kernel = type 0
1106 * client = type 1
1107 *
1108 * return 1 if we found an amalgam.
1109 */
1110int check_amalgam_keyword(void *mask, int type)
1111{
1112 __u64 *k_mask;
1113 struct client_debug_mask *c_mask;
1114 int k_all_index = num_kmod_keyword_mask_map - 1;
1115 int rc = 0;
1116
1117 if (type) {
1118 c_mask = (struct client_debug_mask *) mask;
1119
1120 if ((c_mask->mask1 == cdm_array[client_all_index].mask1) &&
1121 (c_mask->mask2 == cdm_array[client_all_index].mask2)) {
Yi Liu8bb8aef2015-11-24 15:12:14 -05001122 strcpy(client_debug_string, ORANGEFS_ALL);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001123 rc = 1;
1124 goto out;
1125 }
1126
1127 if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) &&
1128 (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) {
Yi Liu8bb8aef2015-11-24 15:12:14 -05001129 strcpy(client_debug_string, ORANGEFS_VERBOSE);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001130 rc = 1;
1131 goto out;
1132 }
1133
1134 } else {
1135 k_mask = (__u64 *) mask;
1136
1137 if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) {
Yi Liu8bb8aef2015-11-24 15:12:14 -05001138 strcpy(kernel_debug_string, ORANGEFS_ALL);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001139 rc = 1;
1140 goto out;
1141 }
1142 }
1143
1144out:
1145
1146 return rc;
1147}
1148
1149/*
1150 * kernel = type 0
1151 * client = type 1
1152 */
1153void debug_string_to_mask(char *debug_string, void *mask, int type)
1154{
1155 char *unchecked_keyword;
1156 int i;
1157 char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
Mike Marshalleeaa3d42015-07-29 13:36:37 -04001158 char *original_pointer;
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001159 int element_count = 0;
1160 struct client_debug_mask *c_mask;
1161 __u64 *k_mask;
1162
1163 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__);
1164
1165 if (type) {
1166 c_mask = (struct client_debug_mask *)mask;
1167 element_count = cdm_element_count;
1168 } else {
1169 k_mask = (__u64 *)mask;
1170 *k_mask = 0;
1171 element_count = num_kmod_keyword_mask_map;
1172 }
1173
Mike Marshalleeaa3d42015-07-29 13:36:37 -04001174 original_pointer = strsep_fodder;
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001175 while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
1176 if (strlen(unchecked_keyword)) {
1177 for (i = 0; i < element_count; i++)
1178 if (type)
1179 do_c_mask(i,
1180 unchecked_keyword,
1181 &c_mask);
1182 else
1183 do_k_mask(i,
1184 unchecked_keyword,
1185 &k_mask);
1186 }
1187
Mike Marshalleeaa3d42015-07-29 13:36:37 -04001188 kfree(original_pointer);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001189}
1190
1191void do_c_mask(int i,
1192 char *unchecked_keyword,
1193 struct client_debug_mask **sane_mask)
1194{
1195
1196 if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) {
1197 (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1;
1198 (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2;
1199 }
1200}
1201
1202void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask)
1203{
1204
1205 if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword))
1206 **sane_mask = (**sane_mask) |
1207 s_kmod_keyword_mask_map[i].mask_val;
1208}