blob: 59c51e2c5a716f9f93248bbc2c6d36d477ef9681 [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
Martin Brandenburgd57521a2016-03-14 16:59:38 -0400173 spin_lock(&inode->i_lock);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400174 inode->i_bytes = inode_size;
175 inode->i_blocks =
176 (unsigned long)(rounded_up_size / 512);
Martin Brandenburgd57521a2016-03-14 16:59:38 -0400177 spin_unlock(&inode->i_lock);
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
Martin Brandenburgd57521a2016-03-14 16:59:38 -0400197 spin_lock(&inode->i_lock);
Mike Marshallf0566532015-08-05 13:46:28 -0400198 inode_set_bytes(inode, inode->i_size);
Martin Brandenburgd57521a2016-03-14 16:59:38 -0400199 spin_unlock(&inode->i_lock);
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 Brandenburg3c9cf982016-03-15 11:28:20 -0400461int orangefs_inode_old_getattr(struct inode *inode, __u32 getattr_mask,
462 int check)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400463{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500464 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
465 struct orangefs_kernel_op_s *new_op;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400466 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
Yi Liu8bb8aef2015-11-24 15:12:14 -0500473 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400474 if (!new_op)
475 return -ENOMEM;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500476 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400477 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
Martin Brandenburg99109822016-01-28 10:19:40 -0500484 if (check) {
485 ret = compare_attributes_to_inode(inode,
486 &new_op->downcall.resp.getattr.attributes,
Martin Brandenburgfe88adc2016-01-30 13:46:11 -0500487 new_op->downcall.resp.getattr.link_target,
488 getattr_mask);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400489
Martin Brandenburg99109822016-01-28 10:19:40 -0500490 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 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400499 } else {
Martin Brandenburg99109822016-01-28 10:19:40 -0500500 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 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400507
Martin Brandenburg99109822016-01-28 10:19:40 -0500508 /*
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 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400525 }
526
527out:
528 gossip_debug(GOSSIP_UTILS_DEBUG,
529 "Getattr on handle %pU, "
530 "fsid %d\n (inode ct = %d) returned %d\n",
Yi Liu8bb8aef2015-11-24 15:12:14 -0500531 &orangefs_inode->refn.khandle,
532 orangefs_inode->refn.fs_id,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400533 (int)atomic_read(&inode->i_count),
534 ret);
535
536 op_release(new_op);
537 return ret;
538}
539
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400540static 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
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400658/*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500659 * issues a orangefs setattr request to make sure the new attribute values
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400660 * take effect if successful. returns 0 on success; -errno otherwise
661 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500662int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400663{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500664 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
665 struct orangefs_kernel_op_s *new_op;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400666 int ret;
667
Yi Liu8bb8aef2015-11-24 15:12:14 -0500668 new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400669 if (!new_op)
670 return -ENOMEM;
671
Yi Liu8bb8aef2015-11-24 15:12:14 -0500672 new_op->upcall.req.setattr.refn = orangefs_inode->refn;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400673 ret = copy_attributes_from_inode(inode,
674 &new_op->upcall.req.setattr.attributes,
675 iattr);
Al Viroed42fe02016-01-22 19:47:47 -0500676 if (ret >= 0) {
677 ret = service_operation(new_op, __func__,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400678 get_interruptible_flag(inode));
679
Al Viroed42fe02016-01-22 19:47:47 -0500680 gossip_debug(GOSSIP_UTILS_DEBUG,
681 "orangefs_inode_setattr: returning %d\n",
682 ret);
683 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400684
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400685 op_release(new_op);
686
687 /*
688 * successful setattr should clear the atime, mtime and
689 * ctime flags.
690 */
691 if (ret == 0) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500692 ClearAtimeFlag(orangefs_inode);
693 ClearMtimeFlag(orangefs_inode);
694 ClearCtimeFlag(orangefs_inode);
695 ClearModeFlag(orangefs_inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400696 }
697
698 return ret;
699}
700
Yi Liu8bb8aef2015-11-24 15:12:14 -0500701int orangefs_flush_inode(struct inode *inode)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400702{
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;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500715 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400716
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 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500724 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);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400732
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,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500753 "*********** orangefs_flush_inode: %pU "
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400754 "(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,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500759 "orangefs_flush_inode skipping setattr()\n");
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400760 return 0;
761 }
762
763 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500764 "orangefs_flush_inode (%pU) writing mode %o\n",
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400765 get_khandle_from_ino(inode),
766 inode->i_mode);
767
Yi Liu8bb8aef2015-11-24 15:12:14 -0500768 ret = orangefs_inode_setattr(inode, &wbattr);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400769
770 return ret;
771}
772
Yi Liu8bb8aef2015-11-24 15:12:14 -0500773int orangefs_unmount_sb(struct super_block *sb)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400774{
775 int ret = -EINVAL;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500776 struct orangefs_kernel_op_s *new_op = NULL;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400777
778 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500779 "orangefs_unmount_sb called on sb %p\n",
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400780 sb);
781
Yi Liu8bb8aef2015-11-24 15:12:14 -0500782 new_op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400783 if (!new_op)
784 return -ENOMEM;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500785 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);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400790
791 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500792 "Attempting ORANGEFS Unmount via host %s\n",
793 new_op->upcall.req.fs_umount.orangefs_config_server);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400794
Yi Liu8bb8aef2015-11-24 15:12:14 -0500795 ret = service_operation(new_op, "orangefs_fs_umount", 0);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400796
797 gossip_debug(GOSSIP_UTILS_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500798 "orangefs_unmount: got return value of %d\n", ret);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400799 if (ret)
800 sb = ERR_PTR(ret);
801 else
Yi Liu8bb8aef2015-11-24 15:12:14 -0500802 ORANGEFS_SB(sb)->mount_pending = 1;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400803
804 op_release(new_op);
805 return ret;
806}
807
Yi Liu8bb8aef2015-11-24 15:12:14 -0500808void orangefs_make_bad_inode(struct inode *inode)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400809{
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
Mike Marshall54804942015-10-05 13:44:24 -0400827/*
828 * The following is a very dirty hack that is now a permanent part of the
Yi Liu8bb8aef2015-11-24 15:12:14 -0500829 * ORANGEFS protocol. See protocol.h for more error definitions.
Mike Marshall54804942015-10-05 13:44:24 -0400830 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400831
Yi Liu8bb8aef2015-11-24 15:12:14 -0500832/* The order matches include/orangefs-types.h in the OrangeFS source. */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400833static int PINT_errno_mapping[] = {
Mike Marshall54804942015-10-05 13:44:24 -0400834 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
Martin Brandenburg894ac432015-10-02 12:11:19 -0400844};
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400845
Yi Liu8bb8aef2015-11-24 15:12:14 -0500846int orangefs_normalize_to_errno(__s32 error_code)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400847{
Mike Marshall54804942015-10-05 13:44:24 -0400848 __u32 i;
849
Martin Brandenburg894ac432015-10-02 12:11:19 -0400850 /* Success */
851 if (error_code == 0) {
852 return 0;
Mike Marshall54804942015-10-05 13:44:24 -0400853 /*
854 * This shouldn't ever happen. If it does it should be fixed on the
855 * server.
856 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400857 } else if (error_code > 0) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500858 gossip_err("orangefs: error status receieved.\n");
859 gossip_err("orangefs: assuming error code is inverted.\n");
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400860 error_code = -error_code;
861 }
862
Mike Marshall54804942015-10-05 13:44:24 -0400863 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500864 * XXX: This is very bad since error codes from ORANGEFS may not be
Mike Marshall54804942015-10-05 13:44:24 -0400865 * suitable for return into userspace.
866 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400867
Mike Marshall54804942015-10-05 13:44:24 -0400868 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500869 * Convert ORANGEFS error values into errno values suitable for return
Mike Marshall54804942015-10-05 13:44:24 -0400870 * from the kernel.
871 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500872 if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
Martin Brandenburg894ac432015-10-02 12:11:19 -0400873 if (((-error_code) &
Yi Liu8bb8aef2015-11-24 15:12:14 -0500874 (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
875 ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400876 /*
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 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500883 gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400884 error_code = -EINVAL;
885 }
Martin Brandenburg894ac432015-10-02 12:11:19 -0400886
Yi Liu8bb8aef2015-11-24 15:12:14 -0500887 /* 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);
Mike Marshall54804942015-10-05 13:44:24 -0400890 if (i < sizeof(PINT_errno_mapping)/sizeof(*PINT_errno_mapping))
Martin Brandenburg894ac432015-10-02 12:11:19 -0400891 error_code = -PINT_errno_mapping[i];
892 else
893 error_code = -EINVAL;
894
Mike Marshall54804942015-10-05 13:44:24 -0400895 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500896 * Only ORANGEFS protocol error codes should ever come here. Otherwise
Mike Marshall54804942015-10-05 13:44:24 -0400897 * there is a bug somewhere.
898 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400899 } else {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500900 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400901 }
902 return error_code;
903}
904
905#define NUM_MODES 11
Yi Liu8bb8aef2015-11-24 15:12:14 -0500906__s32 ORANGEFS_util_translate_mode(int mode)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400907{
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 };
Yi Liu8bb8aef2015-11-24 15:12:14 -0500916 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
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400921 };
922
923 for (i = 0; i < NUM_MODES; i++)
924 if (mode & modes[i])
Yi Liu8bb8aef2015-11-24 15:12:14 -0500925 ret |= orangefs_modes[i];
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400926
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
Yi Liu8bb8aef2015-11-24 15:12:14 -0500987 if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE))
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400988 client_verbose_index = i;
989
Yi Liu8bb8aef2015-11-24 15:12:14 -0500990 if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL))
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400991 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
Yi Liu8bb8aef2015-11-24 15:12:14 -05001126 memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001127
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))
Mike Marshall54804942015-10-05 13:44:24 -04001167 goto out;
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001168
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))
Yi Liu8bb8aef2015-11-24 15:12:14 -05001172 < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) {
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001173 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__);
Yi Liu8bb8aef2015-11-24 15:12:14 -05001178 strcpy(kernel_debug_string, ORANGEFS_ALL);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001179 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)
Yi Liu8bb8aef2015-11-24 15:12:14 -05001199 < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) {
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001200 strcat(client_debug_string,
1201 cdm_array[index].keyword);
1202 strcat(client_debug_string, ",");
1203 } else {
1204 gossip_err("%s: overflow!\n", __func__);
Yi Liu8bb8aef2015-11-24 15:12:14 -05001205 strcpy(client_debug_string, ORANGEFS_ALL);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001206 goto out;
1207 }
1208 }
1209out:
1210 return;
1211}
1212
1213int keyword_is_amalgam(char *keyword)
1214{
1215 int rc = 0;
1216
Yi Liu8bb8aef2015-11-24 15:12:14 -05001217 if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE)))
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001218 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)) {
Yi Liu8bb8aef2015-11-24 15:12:14 -05001241 strcpy(client_debug_string, ORANGEFS_ALL);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001242 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)) {
Yi Liu8bb8aef2015-11-24 15:12:14 -05001248 strcpy(client_debug_string, ORANGEFS_VERBOSE);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001249 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) {
Yi Liu8bb8aef2015-11-24 15:12:14 -05001257 strcpy(kernel_debug_string, ORANGEFS_ALL);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001258 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);
Mike Marshalleeaa3d42015-07-29 13:36:37 -04001277 char *original_pointer;
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001278 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
Mike Marshalleeaa3d42015-07-29 13:36:37 -04001293 original_pointer = strsep_fodder;
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001294 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
Mike Marshalleeaa3d42015-07-29 13:36:37 -04001307 kfree(original_pointer);
Mike Marshallf7be4ee2015-07-17 10:38:14 -04001308}
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}