blob: 00fadaf0da8fb045dd18aff86faee0f052fc7689 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Mike Marshallf7be4ee2015-07-17 10:38:14 -04002/*
3 * (C) 2001 Clemson University and The University of Chicago
4 *
5 * See COPYING in top-level directory.
6 */
Jérémy Lefaure296200d2017-10-01 15:30:48 -04007#include <linux/kernel.h>
Mike Marshallf7be4ee2015-07-17 10:38:14 -04008#include "protocol.h"
Mike Marshall575e9462015-12-04 12:56:14 -05009#include "orangefs-kernel.h"
10#include "orangefs-dev-proto.h"
11#include "orangefs-bufmap.h"
Mike Marshallf7be4ee2015-07-17 10:38:14 -040012
Yi Liu8bb8aef2015-11-24 15:12:14 -050013__s32 fsid_of_op(struct orangefs_kernel_op_s *op)
Mike Marshallf7be4ee2015-07-17 10:38:14 -040014{
Yi Liu8bb8aef2015-11-24 15:12:14 -050015 __s32 fsid = ORANGEFS_FS_ID_NULL;
Mike Marshallf7be4ee2015-07-17 10:38:14 -040016
17 if (op) {
18 switch (op->upcall.type) {
Yi Liu8bb8aef2015-11-24 15:12:14 -050019 case ORANGEFS_VFS_OP_FILE_IO:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040020 fsid = op->upcall.req.io.refn.fs_id;
21 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050022 case ORANGEFS_VFS_OP_LOOKUP:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040023 fsid = op->upcall.req.lookup.parent_refn.fs_id;
24 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050025 case ORANGEFS_VFS_OP_CREATE:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040026 fsid = op->upcall.req.create.parent_refn.fs_id;
27 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050028 case ORANGEFS_VFS_OP_GETATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040029 fsid = op->upcall.req.getattr.refn.fs_id;
30 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050031 case ORANGEFS_VFS_OP_REMOVE:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040032 fsid = op->upcall.req.remove.parent_refn.fs_id;
33 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050034 case ORANGEFS_VFS_OP_MKDIR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040035 fsid = op->upcall.req.mkdir.parent_refn.fs_id;
36 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050037 case ORANGEFS_VFS_OP_READDIR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040038 fsid = op->upcall.req.readdir.refn.fs_id;
39 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050040 case ORANGEFS_VFS_OP_SETATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040041 fsid = op->upcall.req.setattr.refn.fs_id;
42 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050043 case ORANGEFS_VFS_OP_SYMLINK:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040044 fsid = op->upcall.req.sym.parent_refn.fs_id;
45 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050046 case ORANGEFS_VFS_OP_RENAME:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040047 fsid = op->upcall.req.rename.old_parent_refn.fs_id;
48 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050049 case ORANGEFS_VFS_OP_STATFS:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040050 fsid = op->upcall.req.statfs.fs_id;
51 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050052 case ORANGEFS_VFS_OP_TRUNCATE:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040053 fsid = op->upcall.req.truncate.refn.fs_id;
54 break;
Martin Brandenburg6eaff8c2016-08-02 14:31:05 -040055 case ORANGEFS_VFS_OP_RA_FLUSH:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040056 fsid = op->upcall.req.ra_cache_flush.refn.fs_id;
57 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050058 case ORANGEFS_VFS_OP_FS_UMOUNT:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040059 fsid = op->upcall.req.fs_umount.fs_id;
60 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050061 case ORANGEFS_VFS_OP_GETXATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040062 fsid = op->upcall.req.getxattr.refn.fs_id;
63 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050064 case ORANGEFS_VFS_OP_SETXATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040065 fsid = op->upcall.req.setxattr.refn.fs_id;
66 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050067 case ORANGEFS_VFS_OP_LISTXATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040068 fsid = op->upcall.req.listxattr.refn.fs_id;
69 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050070 case ORANGEFS_VFS_OP_REMOVEXATTR:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040071 fsid = op->upcall.req.removexattr.refn.fs_id;
72 break;
Yi Liu8bb8aef2015-11-24 15:12:14 -050073 case ORANGEFS_VFS_OP_FSYNC:
Mike Marshallf7be4ee2015-07-17 10:38:14 -040074 fsid = op->upcall.req.fsync.refn.fs_id;
75 break;
76 default:
77 break;
78 }
79 }
80 return fsid;
81}
82
Martin Brandenburg394f6472016-01-25 15:33:39 -050083static int orangefs_inode_flags(struct ORANGEFS_sys_attr_s *attrs)
Mike Marshallf7be4ee2015-07-17 10:38:14 -040084{
Martin Brandenburg394f6472016-01-25 15:33:39 -050085 int flags = 0;
Yi Liu8bb8aef2015-11-24 15:12:14 -050086 if (attrs->flags & ORANGEFS_IMMUTABLE_FL)
Martin Brandenburg394f6472016-01-25 15:33:39 -050087 flags |= S_IMMUTABLE;
Mike Marshallf7be4ee2015-07-17 10:38:14 -040088 else
Martin Brandenburg394f6472016-01-25 15:33:39 -050089 flags &= ~S_IMMUTABLE;
Yi Liu8bb8aef2015-11-24 15:12:14 -050090 if (attrs->flags & ORANGEFS_APPEND_FL)
Martin Brandenburg394f6472016-01-25 15:33:39 -050091 flags |= S_APPEND;
Mike Marshallf7be4ee2015-07-17 10:38:14 -040092 else
Martin Brandenburg394f6472016-01-25 15:33:39 -050093 flags &= ~S_APPEND;
Yi Liu8bb8aef2015-11-24 15:12:14 -050094 if (attrs->flags & ORANGEFS_NOATIME_FL)
Martin Brandenburg394f6472016-01-25 15:33:39 -050095 flags |= S_NOATIME;
Mike Marshallf7be4ee2015-07-17 10:38:14 -040096 else
Martin Brandenburg394f6472016-01-25 15:33:39 -050097 flags &= ~S_NOATIME;
98 return flags;
99}
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400100
Martin Brandenburg394f6472016-01-25 15:33:39 -0500101static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
102{
103 int perm_mode = 0;
104
105 if (attrs->perms & ORANGEFS_O_EXECUTE)
106 perm_mode |= S_IXOTH;
107 if (attrs->perms & ORANGEFS_O_WRITE)
108 perm_mode |= S_IWOTH;
109 if (attrs->perms & ORANGEFS_O_READ)
110 perm_mode |= S_IROTH;
111
112 if (attrs->perms & ORANGEFS_G_EXECUTE)
113 perm_mode |= S_IXGRP;
114 if (attrs->perms & ORANGEFS_G_WRITE)
115 perm_mode |= S_IWGRP;
116 if (attrs->perms & ORANGEFS_G_READ)
117 perm_mode |= S_IRGRP;
118
119 if (attrs->perms & ORANGEFS_U_EXECUTE)
120 perm_mode |= S_IXUSR;
121 if (attrs->perms & ORANGEFS_U_WRITE)
122 perm_mode |= S_IWUSR;
123 if (attrs->perms & ORANGEFS_U_READ)
124 perm_mode |= S_IRUSR;
125
126 if (attrs->perms & ORANGEFS_G_SGID)
127 perm_mode |= S_ISGID;
128 if (attrs->perms & ORANGEFS_U_SUID)
129 perm_mode |= S_ISUID;
130
131 return perm_mode;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400132}
133
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400134/*
135 * NOTE: in kernel land, we never use the sys_attr->link_target for
136 * anything, so don't bother copying it into the sys_attr object here.
137 */
138static inline int copy_attributes_from_inode(struct inode *inode,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500139 struct ORANGEFS_sys_attr_s *attrs,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400140 struct iattr *iattr)
141{
142 umode_t tmp_mode;
143
144 if (!iattr || !inode || !attrs) {
145 gossip_err("NULL iattr (%p), inode (%p), attrs (%p) "
146 "in copy_attributes_from_inode!\n",
147 iattr,
148 inode,
149 attrs);
150 return -EINVAL;
151 }
152 /*
153 * We need to be careful to only copy the attributes out of the
154 * iattr object that we know are valid.
155 */
156 attrs->mask = 0;
157 if (iattr->ia_valid & ATTR_UID) {
Jann Horn78fee0b2016-06-25 01:51:52 +0200158 attrs->owner = from_kuid(&init_user_ns, iattr->ia_uid);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500159 attrs->mask |= ORANGEFS_ATTR_SYS_UID;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400160 gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
161 }
162 if (iattr->ia_valid & ATTR_GID) {
Jann Horn78fee0b2016-06-25 01:51:52 +0200163 attrs->group = from_kgid(&init_user_ns, iattr->ia_gid);
Yi Liu8bb8aef2015-11-24 15:12:14 -0500164 attrs->mask |= ORANGEFS_ATTR_SYS_GID;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400165 gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
166 }
167
168 if (iattr->ia_valid & ATTR_ATIME) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500169 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400170 if (iattr->ia_valid & ATTR_ATIME_SET) {
Arnd Bergmannbe81ce42016-02-26 13:54:10 +0100171 attrs->atime = (time64_t)iattr->ia_atime.tv_sec;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500172 attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400173 }
174 }
175 if (iattr->ia_valid & ATTR_MTIME) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500176 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400177 if (iattr->ia_valid & ATTR_MTIME_SET) {
Arnd Bergmannbe81ce42016-02-26 13:54:10 +0100178 attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500179 attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400180 }
181 }
182 if (iattr->ia_valid & ATTR_CTIME)
Yi Liu8bb8aef2015-11-24 15:12:14 -0500183 attrs->mask |= ORANGEFS_ATTR_SYS_CTIME;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400184
185 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500186 * ORANGEFS cannot set size with a setattr operation. Probably not likely
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400187 * to be requested through the VFS, but just in case, don't worry about
188 * ATTR_SIZE
189 */
190
191 if (iattr->ia_valid & ATTR_MODE) {
192 tmp_mode = iattr->ia_mode;
193 if (tmp_mode & (S_ISVTX)) {
194 if (is_root_handle(inode)) {
195 /*
196 * allow sticky bit to be set on root (since
197 * it shows up that way by default anyhow),
198 * but don't show it to the server
199 */
200 tmp_mode -= S_ISVTX;
201 } else {
202 gossip_debug(GOSSIP_UTILS_DEBUG,
203 "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
204 return -EINVAL;
205 }
206 }
207
208 if (tmp_mode & (S_ISUID)) {
209 gossip_debug(GOSSIP_UTILS_DEBUG,
210 "Attempting to set setuid bit (not supported); returning EINVAL.\n");
211 return -EINVAL;
212 }
213
Yi Liu8bb8aef2015-11-24 15:12:14 -0500214 attrs->perms = ORANGEFS_util_translate_mode(tmp_mode);
215 attrs->mask |= ORANGEFS_ATTR_SYS_PERM;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400216 }
217
218 return 0;
219}
220
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400221static int orangefs_inode_type(enum orangefs_ds_type objtype)
222{
223 if (objtype == ORANGEFS_TYPE_METAFILE)
224 return S_IFREG;
225 else if (objtype == ORANGEFS_TYPE_DIRECTORY)
226 return S_IFDIR;
227 else if (objtype == ORANGEFS_TYPE_SYMLINK)
228 return S_IFLNK;
229 else
230 return -1;
231}
232
Martin Brandenburg4d0cac72018-01-26 14:07:14 -0500233static void orangefs_make_bad_inode(struct inode *inode)
234{
235 if (is_root_handle(inode)) {
236 /*
237 * if this occurs, the pvfs2-client-core was killed but we
238 * can't afford to lose the inode operations and such
239 * associated with the root handle in any case.
240 */
241 gossip_debug(GOSSIP_UTILS_DEBUG,
242 "*** NOT making bad root inode %pU\n",
243 get_khandle_from_ino(inode));
244 } else {
245 gossip_debug(GOSSIP_UTILS_DEBUG,
246 "*** making bad inode %pU\n",
247 get_khandle_from_ino(inode));
248 make_bad_inode(inode);
249 }
250}
251
Martin Brandenburg480e5ae2018-02-06 14:01:25 +0000252static int orangefs_inode_is_stale(struct inode *inode,
Martin Brandenburg26662632016-03-17 16:01:52 -0400253 struct ORANGEFS_sys_attr_s *attrs, char *link_target)
254{
255 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
256 int type = orangefs_inode_type(attrs->objtype);
Martin Brandenburg480e5ae2018-02-06 14:01:25 +0000257 /*
258 * If the inode type or symlink target have changed then this
259 * inode is stale.
260 */
261 if (type == -1 || !(inode->i_mode & type)) {
262 orangefs_make_bad_inode(inode);
263 return 1;
264 }
265 if (type == S_IFLNK && strncmp(orangefs_inode->link_target,
266 link_target, ORANGEFS_NAME_MAX)) {
267 orangefs_make_bad_inode(inode);
268 return 1;
Martin Brandenburg26662632016-03-17 16:01:52 -0400269 }
270 return 0;
271}
272
Martin Brandenburg68a24a62017-04-25 15:38:03 -0400273int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
274 u32 request_mask)
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400275{
276 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
277 struct orangefs_kernel_op_s *new_op;
278 loff_t inode_size, rounded_up_size;
Martin Brandenburg26662632016-03-17 16:01:52 -0400279 int ret, type;
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400280
281 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
282 get_khandle_from_ino(inode));
283
Martin Brandenburg71680c12016-06-09 16:32:38 -0400284 if (!new && !bypass) {
Martin Brandenburg68a24a62017-04-25 15:38:03 -0400285 /*
286 * Must have all the attributes in the mask and be within cache
287 * time.
288 */
289 if ((request_mask & orangefs_inode->getattr_mask) ==
290 request_mask &&
291 time_before(jiffies, orangefs_inode->getattr_time))
Martin Brandenburg71680c12016-06-09 16:32:38 -0400292 return 0;
293 }
294
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400295 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
296 if (!new_op)
297 return -ENOMEM;
298 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
Martin Brandenburg68a24a62017-04-25 15:38:03 -0400299 /*
300 * Size is the hardest attribute to get. The incremental cost of any
301 * other attribute is essentially zero.
302 */
303 if (request_mask & STATX_SIZE || new)
304 new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
305 else
306 new_op->upcall.req.getattr.mask =
307 ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400308
309 ret = service_operation(new_op, __func__,
310 get_interruptible_flag(inode));
311 if (ret != 0)
312 goto out;
313
Martin Brandenburg480e5ae2018-02-06 14:01:25 +0000314 if (!new) {
315 ret = orangefs_inode_is_stale(inode,
316 &new_op->downcall.resp.getattr.attributes,
317 new_op->downcall.resp.getattr.link_target);
318 if (ret) {
319 ret = -ESTALE;
320 goto out;
321 }
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400322 }
323
Martin Brandenburg480e5ae2018-02-06 14:01:25 +0000324 type = orangefs_inode_type(new_op->
325 downcall.resp.getattr.attributes.objtype);
Martin Brandenburg26662632016-03-17 16:01:52 -0400326 switch (type) {
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400327 case S_IFREG:
328 inode->i_flags = orangefs_inode_flags(&new_op->
329 downcall.resp.getattr.attributes);
Martin Brandenburg68a24a62017-04-25 15:38:03 -0400330 if (request_mask & STATX_SIZE || new) {
331 inode_size = (loff_t)new_op->
332 downcall.resp.getattr.attributes.size;
333 rounded_up_size =
334 (inode_size + (4096 - (inode_size % 4096)));
335 inode->i_size = inode_size;
336 orangefs_inode->blksize =
337 new_op->downcall.resp.getattr.attributes.blksize;
338 spin_lock(&inode->i_lock);
339 inode->i_bytes = inode_size;
340 inode->i_blocks =
341 (unsigned long)(rounded_up_size / 512);
342 spin_unlock(&inode->i_lock);
343 }
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400344 break;
345 case S_IFDIR:
Martin Brandenburg68a24a62017-04-25 15:38:03 -0400346 if (request_mask & STATX_SIZE || new) {
347 inode->i_size = PAGE_SIZE;
348 orangefs_inode->blksize = i_blocksize(inode);
349 spin_lock(&inode->i_lock);
350 inode_set_bytes(inode, inode->i_size);
351 spin_unlock(&inode->i_lock);
352 }
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400353 set_nlink(inode, 1);
354 break;
355 case S_IFLNK:
356 if (new) {
357 inode->i_size = (loff_t)strlen(new_op->
358 downcall.resp.getattr.link_target);
Fabian Frederick93407472017-02-27 14:28:32 -0800359 orangefs_inode->blksize = i_blocksize(inode);
Martin Brandenburg2eacea72016-04-08 13:33:21 -0400360 ret = strscpy(orangefs_inode->link_target,
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400361 new_op->downcall.resp.getattr.link_target,
362 ORANGEFS_NAME_MAX);
Martin Brandenburg2eacea72016-04-08 13:33:21 -0400363 if (ret == -E2BIG) {
364 ret = -EIO;
365 goto out;
366 }
Martin Brandenburge8da2542016-03-18 14:20:15 -0400367 inode->i_link = orangefs_inode->link_target;
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400368 }
369 break;
Martin Brandenburg480e5ae2018-02-06 14:01:25 +0000370 /* i.e. -1 */
371 default:
372 /* XXX: ESTALE? This is what is done if it is not new. */
373 orangefs_make_bad_inode(inode);
374 ret = -ESTALE;
375 goto out;
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400376 }
377
378 inode->i_uid = make_kuid(&init_user_ns, new_op->
379 downcall.resp.getattr.attributes.owner);
380 inode->i_gid = make_kgid(&init_user_ns, new_op->
381 downcall.resp.getattr.attributes.group);
382 inode->i_atime.tv_sec = (time64_t)new_op->
383 downcall.resp.getattr.attributes.atime;
384 inode->i_mtime.tv_sec = (time64_t)new_op->
385 downcall.resp.getattr.attributes.mtime;
386 inode->i_ctime.tv_sec = (time64_t)new_op->
387 downcall.resp.getattr.attributes.ctime;
388 inode->i_atime.tv_nsec = 0;
389 inode->i_mtime.tv_nsec = 0;
390 inode->i_ctime.tv_nsec = 0;
391
392 /* special case: mark the root inode as sticky */
Martin Brandenburg26662632016-03-17 16:01:52 -0400393 inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400394 orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
395
Martin Brandenburg1d503612016-08-16 11:38:14 -0400396 orangefs_inode->getattr_time = jiffies +
397 orangefs_getattr_timeout_msecs*HZ/1000;
Martin Brandenburg68a24a62017-04-25 15:38:03 -0400398 if (request_mask & STATX_SIZE || new)
399 orangefs_inode->getattr_mask = STATX_BASIC_STATS;
400 else
401 orangefs_inode->getattr_mask = STATX_BASIC_STATS & ~STATX_SIZE;
Martin Brandenburg3c9cf982016-03-15 11:28:20 -0400402 ret = 0;
403out:
404 op_release(new_op);
405 return ret;
406}
407
Martin Brandenburg5859d772016-03-17 15:15:16 -0400408int orangefs_inode_check_changed(struct inode *inode)
409{
410 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
411 struct orangefs_kernel_op_s *new_op;
412 int ret;
413
414 gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
415 get_khandle_from_ino(inode));
416
417 new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
418 if (!new_op)
419 return -ENOMEM;
420 new_op->upcall.req.getattr.refn = orangefs_inode->refn;
421 new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE |
422 ORANGEFS_ATTR_SYS_LNK_TARGET;
423
424 ret = service_operation(new_op, __func__,
425 get_interruptible_flag(inode));
426 if (ret != 0)
427 goto out;
428
Martin Brandenburg480e5ae2018-02-06 14:01:25 +0000429 ret = orangefs_inode_is_stale(inode,
Martin Brandenburg26662632016-03-17 16:01:52 -0400430 &new_op->downcall.resp.getattr.attributes,
431 new_op->downcall.resp.getattr.link_target);
Martin Brandenburg5859d772016-03-17 15:15:16 -0400432out:
433 op_release(new_op);
434 return ret;
435}
436
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400437/*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500438 * issues a orangefs setattr request to make sure the new attribute values
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400439 * take effect if successful. returns 0 on success; -errno otherwise
440 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500441int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400442{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500443 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
444 struct orangefs_kernel_op_s *new_op;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400445 int ret;
446
Yi Liu8bb8aef2015-11-24 15:12:14 -0500447 new_op = op_alloc(ORANGEFS_VFS_OP_SETATTR);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400448 if (!new_op)
449 return -ENOMEM;
450
Yi Liu8bb8aef2015-11-24 15:12:14 -0500451 new_op->upcall.req.setattr.refn = orangefs_inode->refn;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400452 ret = copy_attributes_from_inode(inode,
453 &new_op->upcall.req.setattr.attributes,
454 iattr);
Al Viroed42fe02016-01-22 19:47:47 -0500455 if (ret >= 0) {
456 ret = service_operation(new_op, __func__,
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400457 get_interruptible_flag(inode));
458
Al Viroed42fe02016-01-22 19:47:47 -0500459 gossip_debug(GOSSIP_UTILS_DEBUG,
460 "orangefs_inode_setattr: returning %d\n",
461 ret);
462 }
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400463
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400464 op_release(new_op);
465
Martin Brandenburga55f2d82017-11-07 15:01:40 -0500466 if (ret == 0)
Martin Brandenburg8bbb20a2016-07-28 14:46:36 -0400467 orangefs_inode->getattr_time = jiffies - 1;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400468
469 return ret;
470}
471
Mike Marshall54804942015-10-05 13:44:24 -0400472/*
473 * The following is a very dirty hack that is now a permanent part of the
Yi Liu8bb8aef2015-11-24 15:12:14 -0500474 * ORANGEFS protocol. See protocol.h for more error definitions.
Mike Marshall54804942015-10-05 13:44:24 -0400475 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400476
Yi Liu8bb8aef2015-11-24 15:12:14 -0500477/* The order matches include/orangefs-types.h in the OrangeFS source. */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400478static int PINT_errno_mapping[] = {
Mike Marshall54804942015-10-05 13:44:24 -0400479 0, EPERM, ENOENT, EINTR, EIO, ENXIO, EBADF, EAGAIN, ENOMEM,
480 EFAULT, EBUSY, EEXIST, ENODEV, ENOTDIR, EISDIR, EINVAL, EMFILE,
481 EFBIG, ENOSPC, EROFS, EMLINK, EPIPE, EDEADLK, ENAMETOOLONG,
482 ENOLCK, ENOSYS, ENOTEMPTY, ELOOP, EWOULDBLOCK, ENOMSG, EUNATCH,
483 EBADR, EDEADLOCK, ENODATA, ETIME, ENONET, EREMOTE, ECOMM,
484 EPROTO, EBADMSG, EOVERFLOW, ERESTART, EMSGSIZE, EPROTOTYPE,
485 ENOPROTOOPT, EPROTONOSUPPORT, EOPNOTSUPP, EADDRINUSE,
486 EADDRNOTAVAIL, ENETDOWN, ENETUNREACH, ENETRESET, ENOBUFS,
487 ETIMEDOUT, ECONNREFUSED, EHOSTDOWN, EHOSTUNREACH, EALREADY,
488 EACCES, ECONNRESET, ERANGE
Martin Brandenburg894ac432015-10-02 12:11:19 -0400489};
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400490
Yi Liu8bb8aef2015-11-24 15:12:14 -0500491int orangefs_normalize_to_errno(__s32 error_code)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400492{
Mike Marshall54804942015-10-05 13:44:24 -0400493 __u32 i;
494
Martin Brandenburg894ac432015-10-02 12:11:19 -0400495 /* Success */
496 if (error_code == 0) {
497 return 0;
Mike Marshall54804942015-10-05 13:44:24 -0400498 /*
499 * This shouldn't ever happen. If it does it should be fixed on the
500 * server.
501 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400502 } else if (error_code > 0) {
Masanari Iidabc8282a2018-01-16 00:18:36 +0900503 gossip_err("orangefs: error status received.\n");
Yi Liu8bb8aef2015-11-24 15:12:14 -0500504 gossip_err("orangefs: assuming error code is inverted.\n");
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400505 error_code = -error_code;
506 }
507
Mike Marshall54804942015-10-05 13:44:24 -0400508 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500509 * XXX: This is very bad since error codes from ORANGEFS may not be
Mike Marshall54804942015-10-05 13:44:24 -0400510 * suitable for return into userspace.
511 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400512
Mike Marshall54804942015-10-05 13:44:24 -0400513 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500514 * Convert ORANGEFS error values into errno values suitable for return
Mike Marshall54804942015-10-05 13:44:24 -0400515 * from the kernel.
516 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500517 if ((-error_code) & ORANGEFS_NON_ERRNO_ERROR_BIT) {
Martin Brandenburg894ac432015-10-02 12:11:19 -0400518 if (((-error_code) &
Yi Liu8bb8aef2015-11-24 15:12:14 -0500519 (ORANGEFS_ERROR_NUMBER_BITS|ORANGEFS_NON_ERRNO_ERROR_BIT|
520 ORANGEFS_ERROR_BIT)) == ORANGEFS_ECANCEL) {
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400521 /*
522 * cancellation error codes generally correspond to
523 * a timeout from the client's perspective
524 */
525 error_code = -ETIMEDOUT;
526 } else {
527 /* assume a default error code */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500528 gossip_err("orangefs: warning: got error code without errno equivalent: %d.\n", error_code);
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400529 error_code = -EINVAL;
530 }
Martin Brandenburg894ac432015-10-02 12:11:19 -0400531
Yi Liu8bb8aef2015-11-24 15:12:14 -0500532 /* Convert ORANGEFS encoded errno values into regular errno values. */
533 } else if ((-error_code) & ORANGEFS_ERROR_BIT) {
534 i = (-error_code) & ~(ORANGEFS_ERROR_BIT|ORANGEFS_ERROR_CLASS_BITS);
Jérémy Lefaure296200d2017-10-01 15:30:48 -0400535 if (i < ARRAY_SIZE(PINT_errno_mapping))
Martin Brandenburg894ac432015-10-02 12:11:19 -0400536 error_code = -PINT_errno_mapping[i];
537 else
538 error_code = -EINVAL;
539
Mike Marshall54804942015-10-05 13:44:24 -0400540 /*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500541 * Only ORANGEFS protocol error codes should ever come here. Otherwise
Mike Marshall54804942015-10-05 13:44:24 -0400542 * there is a bug somewhere.
543 */
Martin Brandenburg894ac432015-10-02 12:11:19 -0400544 } else {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500545 gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n");
Mike Marshallcf546ab2018-01-25 14:43:28 -0500546 error_code = -EINVAL;
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400547 }
548 return error_code;
549}
550
551#define NUM_MODES 11
Yi Liu8bb8aef2015-11-24 15:12:14 -0500552__s32 ORANGEFS_util_translate_mode(int mode)
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400553{
554 int ret = 0;
555 int i = 0;
556 static int modes[NUM_MODES] = {
557 S_IXOTH, S_IWOTH, S_IROTH,
558 S_IXGRP, S_IWGRP, S_IRGRP,
559 S_IXUSR, S_IWUSR, S_IRUSR,
560 S_ISGID, S_ISUID
561 };
Yi Liu8bb8aef2015-11-24 15:12:14 -0500562 static int orangefs_modes[NUM_MODES] = {
563 ORANGEFS_O_EXECUTE, ORANGEFS_O_WRITE, ORANGEFS_O_READ,
564 ORANGEFS_G_EXECUTE, ORANGEFS_G_WRITE, ORANGEFS_G_READ,
565 ORANGEFS_U_EXECUTE, ORANGEFS_U_WRITE, ORANGEFS_U_READ,
566 ORANGEFS_G_SGID, ORANGEFS_U_SUID
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400567 };
568
569 for (i = 0; i < NUM_MODES; i++)
570 if (mode & modes[i])
Yi Liu8bb8aef2015-11-24 15:12:14 -0500571 ret |= orangefs_modes[i];
Mike Marshallf7be4ee2015-07-17 10:38:14 -0400572
573 return ret;
574}
575#undef NUM_MODES