blob: 1c72aa38317ddae2454050a7cb3f56391a827dce [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Mike Marshall5db11c22015-07-17 10:38:12 -04002/*
3 * (C) 2001 Clemson University and The University of Chicago
Martin Brandenburgafd9fb22018-02-13 20:13:46 +00004 * Copyright 2018 Omnibond Systems, L.L.C.
Mike Marshall5db11c22015-07-17 10:38:12 -04005 *
6 * See COPYING in top-level directory.
7 */
8
9/*
10 * Linux VFS inode operations.
11 */
12
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060013#include <linux/bvec.h>
Mike Marshall5db11c22015-07-17 10:38:12 -040014#include "protocol.h"
Mike Marshall575e9462015-12-04 12:56:14 -050015#include "orangefs-kernel.h"
16#include "orangefs-bufmap.h"
Mike Marshall5db11c22015-07-17 10:38:12 -040017
Martin Brandenburg85ac7992018-02-22 18:10:43 +000018static int orangefs_writepage(struct page *page, struct writeback_control *wbc)
19{
20 struct inode *inode = page->mapping->host;
21 struct iov_iter iter;
22 struct bio_vec bv;
23 size_t len, wlen;
24 ssize_t ret;
25 loff_t off;
26
27 set_page_writeback(page);
28
29 off = page_offset(page);
30 len = i_size_read(inode);
31 if (off > len) {
32 /* The file was truncated; there is nothing to write. */
33 unlock_page(page);
34 end_page_writeback(page);
35 return 0;
36 }
37 if (off + PAGE_SIZE > len)
38 wlen = len - off;
39 else
40 wlen = PAGE_SIZE;
41
42 bv.bv_page = page;
43 bv.bv_len = wlen;
44 bv.bv_offset = off % PAGE_SIZE;
45 if (wlen == 0)
46 dump_stack();
47 iov_iter_bvec(&iter, WRITE, &bv, 1, wlen);
48
49 ret = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, wlen,
50 len);
51 if (ret < 0) {
52 SetPageError(page);
53 mapping_set_error(page->mapping, ret);
54 } else {
55 ret = 0;
56 }
57 unlock_page(page);
58 end_page_writeback(page);
59 return ret;
60}
61
Martin Brandenburga68d9c62018-02-15 18:02:43 +000062static int orangefs_readpage(struct file *file, struct page *page)
Mike Marshall5db11c22015-07-17 10:38:12 -040063{
Mike Marshall5db11c22015-07-17 10:38:12 -040064 struct inode *inode = page->mapping->host;
Martin Brandenburgc453dcf2018-02-16 20:51:24 +000065 struct iov_iter iter;
66 struct bio_vec bv;
67 ssize_t ret;
68 loff_t off;
Al Viro74f68fc2015-10-08 18:31:05 -040069
Martin Brandenburgc453dcf2018-02-16 20:51:24 +000070 off = page_offset(page);
71 bv.bv_page = page;
72 bv.bv_len = PAGE_SIZE;
73 bv.bv_offset = 0;
74 iov_iter_bvec(&iter, READ, &bv, 1, PAGE_SIZE);
Mike Marshall5db11c22015-07-17 10:38:12 -040075
Martin Brandenburgc453dcf2018-02-16 20:51:24 +000076 ret = wait_for_direct_io(ORANGEFS_IO_READ, inode, &off, &iter,
77 PAGE_SIZE, inode->i_size);
Al Viro74f68fc2015-10-08 18:31:05 -040078 /* this will only zero remaining unread portions of the page data */
Martin Brandenburgc453dcf2018-02-16 20:51:24 +000079 iov_iter_zero(~0U, &iter);
Mike Marshall5db11c22015-07-17 10:38:12 -040080 /* takes care of potential aliasing */
81 flush_dcache_page(page);
Martin Brandenburgc453dcf2018-02-16 20:51:24 +000082 if (ret < 0) {
Mike Marshall5db11c22015-07-17 10:38:12 -040083 SetPageError(page);
84 } else {
85 SetPageUptodate(page);
86 if (PageError(page))
87 ClearPageError(page);
88 ret = 0;
89 }
Mike Marshall5db11c22015-07-17 10:38:12 -040090 /* unlock the page after the ->readpage() routine completes */
91 unlock_page(page);
92 return ret;
93}
94
Martin Brandenburg85ac7992018-02-22 18:10:43 +000095static int orangefs_write_end(struct file *file, struct address_space *mapping,
96 loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata)
97{
98 int r;
99 r = simple_write_end(file, mapping, pos, len, copied, page, fsdata);
100 mark_inode_dirty_sync(file_inode(file));
101 return r;
102}
103
Yi Liu8bb8aef2015-11-24 15:12:14 -0500104static void orangefs_invalidatepage(struct page *page,
Mike Marshall5db11c22015-07-17 10:38:12 -0400105 unsigned int offset,
106 unsigned int length)
107{
108 gossip_debug(GOSSIP_INODE_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500109 "orangefs_invalidatepage called on page %p "
Mike Marshall5db11c22015-07-17 10:38:12 -0400110 "(offset is %u)\n",
111 page,
112 offset);
113
114 ClearPageUptodate(page);
115 ClearPageMappedToDisk(page);
116 return;
117
118}
119
Yi Liu8bb8aef2015-11-24 15:12:14 -0500120static int orangefs_releasepage(struct page *page, gfp_t foo)
Mike Marshall5db11c22015-07-17 10:38:12 -0400121{
122 gossip_debug(GOSSIP_INODE_DEBUG,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500123 "orangefs_releasepage called on page %p\n",
Mike Marshall5db11c22015-07-17 10:38:12 -0400124 page);
125 return 0;
126}
127
Mike Marshall3903f152016-06-09 15:38:03 -0400128static ssize_t orangefs_direct_IO(struct kiocb *iocb,
129 struct iov_iter *iter)
130{
Martin Brandenburg3e9dfc62018-11-06 19:54:49 +0000131 /*
132 * Comment from original do_readv_writev:
133 * Common entry point for read/write/readv/writev
134 * This function will dispatch it to either the direct I/O
135 * or buffered I/O path depending on the mount options and/or
136 * augmented/extended metadata attached to the file.
137 * Note: File extended attributes override any mount options.
138 */
Martin Brandenburgc453dcf2018-02-16 20:51:24 +0000139 struct file *file = iocb->ki_filp;
Martin Brandenburg3e9dfc62018-11-06 19:54:49 +0000140 loff_t pos = iocb->ki_pos;
141 enum ORANGEFS_io_type type = iov_iter_rw(iter) == WRITE ?
142 ORANGEFS_IO_WRITE : ORANGEFS_IO_READ;
143 loff_t *offset = &pos;
144 struct inode *inode = file->f_mapping->host;
145 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
146 struct orangefs_khandle *handle = &orangefs_inode->refn.khandle;
147 size_t count = iov_iter_count(iter);
148 size_t ORIGINALcount = iov_iter_count(iter);
149 ssize_t total_count = 0;
150 ssize_t ret = -EINVAL;
151 int i = 0;
152
153 gossip_debug(GOSSIP_FILE_DEBUG,
154 "%s-BEGIN(%pU): count(%d) after estimate_max_iovecs.\n",
155 __func__,
156 handle,
157 (int)count);
158
159 if (type == ORANGEFS_IO_WRITE) {
160 gossip_debug(GOSSIP_FILE_DEBUG,
161 "%s(%pU): proceeding with offset : %llu, "
162 "size %d\n",
163 __func__,
164 handle,
165 llu(*offset),
166 (int)count);
167 }
168
169 if (count == 0) {
170 ret = 0;
171 goto out;
172 }
173
174 while (iov_iter_count(iter)) {
175 size_t each_count = iov_iter_count(iter);
176 size_t amt_complete;
177 i++;
178
179 /* how much to transfer in this loop iteration */
180 if (each_count > orangefs_bufmap_size_query())
181 each_count = orangefs_bufmap_size_query();
182
183 gossip_debug(GOSSIP_FILE_DEBUG,
184 "%s(%pU): size of each_count(%d)\n",
185 __func__,
186 handle,
187 (int)each_count);
188 gossip_debug(GOSSIP_FILE_DEBUG,
189 "%s(%pU): BEFORE wait_for_io: offset is %d\n",
190 __func__,
191 handle,
192 (int)*offset);
193
194 ret = wait_for_direct_io(type, inode, offset, iter,
195 each_count, 0);
196 gossip_debug(GOSSIP_FILE_DEBUG,
197 "%s(%pU): return from wait_for_io:%d\n",
198 __func__,
199 handle,
200 (int)ret);
201
202 if (ret < 0)
203 goto out;
204
205 *offset += ret;
206 total_count += ret;
207 amt_complete = ret;
208
209 gossip_debug(GOSSIP_FILE_DEBUG,
210 "%s(%pU): AFTER wait_for_io: offset is %d\n",
211 __func__,
212 handle,
213 (int)*offset);
214
215 /*
216 * if we got a short I/O operations,
217 * fall out and return what we got so far
218 */
219 if (amt_complete < each_count)
220 break;
221 } /*end while */
222
223out:
224 if (total_count > 0)
225 ret = total_count;
226 if (ret > 0) {
227 if (type == ORANGEFS_IO_READ) {
228 file_accessed(file);
229 } else {
230 file_update_time(file);
231 if (*offset > i_size_read(inode))
232 i_size_write(inode, *offset);
233 }
234 }
235
236 gossip_debug(GOSSIP_FILE_DEBUG,
237 "%s(%pU): Value(%d) returned.\n",
238 __func__,
239 handle,
240 (int)ret);
241
242 return ret;
Mike Marshall3903f152016-06-09 15:38:03 -0400243}
Mike Marshall5db11c22015-07-17 10:38:12 -0400244
Yi Liu8bb8aef2015-11-24 15:12:14 -0500245/** ORANGEFS2 implementation of address space operations */
Martin Brandenburgbdd6f082018-04-03 16:27:13 +0000246static const struct address_space_operations orangefs_address_operations = {
Martin Brandenburg85ac7992018-02-22 18:10:43 +0000247 .writepage = orangefs_writepage,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500248 .readpage = orangefs_readpage,
Martin Brandenburg85ac7992018-02-22 18:10:43 +0000249 .set_page_dirty = __set_page_dirty_nobuffers,
250 .write_begin = simple_write_begin,
251 .write_end = orangefs_write_end,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500252 .invalidatepage = orangefs_invalidatepage,
253 .releasepage = orangefs_releasepage,
Mike Marshall3903f152016-06-09 15:38:03 -0400254 .direct_IO = orangefs_direct_IO,
Mike Marshall5db11c22015-07-17 10:38:12 -0400255};
256
Yi Liu8bb8aef2015-11-24 15:12:14 -0500257static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
Mike Marshall5db11c22015-07-17 10:38:12 -0400258{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500259 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
260 struct orangefs_kernel_op_s *new_op;
Martin Brandenburgfecd86a2016-03-23 17:06:25 -0400261 loff_t orig_size;
Mike Marshall5db11c22015-07-17 10:38:12 -0400262 int ret = -EINVAL;
263
264 gossip_debug(GOSSIP_INODE_DEBUG,
265 "%s: %pU: Handle is %pU | fs_id %d | size is %llu\n",
266 __func__,
267 get_khandle_from_ino(inode),
Yi Liu8bb8aef2015-11-24 15:12:14 -0500268 &orangefs_inode->refn.khandle,
269 orangefs_inode->refn.fs_id,
Mike Marshall5db11c22015-07-17 10:38:12 -0400270 iattr->ia_size);
271
Martin Brandenburgfecd86a2016-03-23 17:06:25 -0400272 /* Ensure that we have a up to date size, so we know if it changed. */
Martin Brandenburg8b607852018-02-07 18:44:50 +0000273 ret = orangefs_inode_getattr(inode, ORANGEFS_GETATTR_SIZE);
Martin Brandenburgfecd86a2016-03-23 17:06:25 -0400274 if (ret == -ESTALE)
275 ret = -EIO;
276 if (ret) {
277 gossip_err("%s: orangefs_inode_getattr failed, ret:%d:.\n",
278 __func__, ret);
279 return ret;
280 }
281 orig_size = i_size_read(inode);
282
Mike Marshall5db11c22015-07-17 10:38:12 -0400283 truncate_setsize(inode, iattr->ia_size);
284
Yi Liu8bb8aef2015-11-24 15:12:14 -0500285 new_op = op_alloc(ORANGEFS_VFS_OP_TRUNCATE);
Mike Marshall5db11c22015-07-17 10:38:12 -0400286 if (!new_op)
287 return -ENOMEM;
288
Yi Liu8bb8aef2015-11-24 15:12:14 -0500289 new_op->upcall.req.truncate.refn = orangefs_inode->refn;
Mike Marshall5db11c22015-07-17 10:38:12 -0400290 new_op->upcall.req.truncate.size = (__s64) iattr->ia_size;
291
Mike Marshall95f5f882018-05-11 17:11:48 -0400292 ret = service_operation(new_op,
293 __func__,
294 get_interruptible_flag(inode));
Mike Marshall5db11c22015-07-17 10:38:12 -0400295
296 /*
297 * the truncate has no downcall members to retrieve, but
298 * the status value tells us if it went through ok or not
299 */
Mike Marshall95f5f882018-05-11 17:11:48 -0400300 gossip_debug(GOSSIP_INODE_DEBUG, "%s: ret:%d:\n", __func__, ret);
Mike Marshall5db11c22015-07-17 10:38:12 -0400301
302 op_release(new_op);
303
304 if (ret != 0)
305 return ret;
306
Martin Brandenburgf83140c2016-04-04 16:26:36 -0400307 if (orig_size != i_size_read(inode))
Mike Marshall5db11c22015-07-17 10:38:12 -0400308 iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
Mike Marshall5db11c22015-07-17 10:38:12 -0400309
310 return ret;
311}
312
Martin Brandenburgafd9fb22018-02-13 20:13:46 +0000313int __orangefs_setattr(struct inode *inode, struct iattr *iattr)
Mike Marshall5db11c22015-07-17 10:38:12 -0400314{
Martin Brandenburgdf2d7332018-02-12 20:29:37 +0000315 int ret;
Mike Marshall5db11c22015-07-17 10:38:12 -0400316
Martin Brandenburgafd9fb22018-02-13 20:13:46 +0000317 if (iattr->ia_valid & ATTR_MODE) {
318 if (iattr->ia_mode & (S_ISVTX)) {
319 if (is_root_handle(inode)) {
320 /*
321 * allow sticky bit to be set on root (since
322 * it shows up that way by default anyhow),
323 * but don't show it to the server
324 */
325 iattr->ia_mode -= S_ISVTX;
326 } else {
327 gossip_debug(GOSSIP_UTILS_DEBUG,
328 "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
329 return -EINVAL;
330 }
331 }
332 if (iattr->ia_mode & (S_ISUID)) {
333 gossip_debug(GOSSIP_UTILS_DEBUG,
334 "Attempting to set setuid bit (not supported); returning EINVAL.\n");
335 return -EINVAL;
336 }
337 }
Mike Marshall5db11c22015-07-17 10:38:12 -0400338
Martin Brandenburg53950ef2017-04-25 15:38:04 -0400339 if (iattr->ia_valid & ATTR_SIZE) {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500340 ret = orangefs_setattr_size(inode, iattr);
Mike Marshall5db11c22015-07-17 10:38:12 -0400341 if (ret)
342 goto out;
343 }
344
Martin Brandenburgafd9fb22018-02-13 20:13:46 +0000345again:
346 spin_lock(&inode->i_lock);
347 if (ORANGEFS_I(inode)->attr_valid) {
348 if (uid_eq(ORANGEFS_I(inode)->attr_uid, current_fsuid()) &&
349 gid_eq(ORANGEFS_I(inode)->attr_gid, current_fsgid())) {
350 ORANGEFS_I(inode)->attr_valid = iattr->ia_valid;
351 } else {
352 spin_unlock(&inode->i_lock);
353 write_inode_now(inode, 1);
354 goto again;
355 }
356 } else {
357 ORANGEFS_I(inode)->attr_valid = iattr->ia_valid;
358 ORANGEFS_I(inode)->attr_uid = current_fsuid();
359 ORANGEFS_I(inode)->attr_gid = current_fsgid();
360 }
Mike Marshall5db11c22015-07-17 10:38:12 -0400361 setattr_copy(inode, iattr);
Martin Brandenburgafd9fb22018-02-13 20:13:46 +0000362 spin_unlock(&inode->i_lock);
Mike Marshall5db11c22015-07-17 10:38:12 -0400363 mark_inode_dirty(inode);
364
Martin Brandenburgdf2d7332018-02-12 20:29:37 +0000365 if (iattr->ia_valid & ATTR_MODE)
Mike Marshall5db11c22015-07-17 10:38:12 -0400366 /* change mod on a file that has ACLs */
367 ret = posix_acl_chmod(inode, inode->i_mode);
368
Martin Brandenburgdf2d7332018-02-12 20:29:37 +0000369 ret = 0;
Mike Marshall5db11c22015-07-17 10:38:12 -0400370out:
Martin Brandenburgafd9fb22018-02-13 20:13:46 +0000371 return ret;
372}
373
374/*
375 * Change attributes of an object referenced by dentry.
376 */
377int orangefs_setattr(struct dentry *dentry, struct iattr *iattr)
378{
379 int ret;
380 gossip_debug(GOSSIP_INODE_DEBUG, "__orangefs_setattr: called on %pd\n",
381 dentry);
382 ret = setattr_prepare(dentry, iattr);
383 if (ret)
384 goto out;
385 ret = __orangefs_setattr(d_inode(dentry), iattr);
386 sync_inode_metadata(d_inode(dentry), 1);
387out:
388 gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_setattr: returning %d\n",
389 ret);
Mike Marshall5db11c22015-07-17 10:38:12 -0400390 return ret;
391}
392
393/*
394 * Obtain attributes of an object given a dentry
395 */
David Howellsa528d352017-01-31 16:46:22 +0000396int orangefs_getattr(const struct path *path, struct kstat *stat,
397 u32 request_mask, unsigned int flags)
Mike Marshall5db11c22015-07-17 10:38:12 -0400398{
399 int ret = -ENOENT;
David Howellsa528d352017-01-31 16:46:22 +0000400 struct inode *inode = path->dentry->d_inode;
Mike Marshall5db11c22015-07-17 10:38:12 -0400401
402 gossip_debug(GOSSIP_INODE_DEBUG,
Martin Brandenburg5e4f6062018-02-12 17:04:57 +0000403 "orangefs_getattr: called on %pd mask %u\n",
404 path->dentry, request_mask);
Mike Marshall5db11c22015-07-17 10:38:12 -0400405
Martin Brandenburg8b607852018-02-07 18:44:50 +0000406 ret = orangefs_inode_getattr(inode,
407 request_mask & STATX_SIZE ? ORANGEFS_GETATTR_SIZE : 0);
Mike Marshall5db11c22015-07-17 10:38:12 -0400408 if (ret == 0) {
David Howellsa528d352017-01-31 16:46:22 +0000409 generic_fillattr(inode, stat);
Mike Marshalla7d3e782016-03-14 15:30:03 -0400410
Mike Marshall5db11c22015-07-17 10:38:12 -0400411 /* override block size reported to stat */
Christoph Hellwig5678b5d2019-01-21 16:23:25 +0100412 if (!(request_mask & STATX_SIZE))
413 stat->result_mask &= ~STATX_SIZE;
Martin Brandenburg7f549102018-05-31 16:37:00 +0000414
415 stat->attributes_mask = STATX_ATTR_IMMUTABLE |
416 STATX_ATTR_APPEND;
417 if (inode->i_flags & S_IMMUTABLE)
418 stat->attributes |= STATX_ATTR_IMMUTABLE;
419 if (inode->i_flags & S_APPEND)
420 stat->attributes |= STATX_ATTR_APPEND;
Mike Marshall5db11c22015-07-17 10:38:12 -0400421 }
422 return ret;
423}
424
Martin Brandenburg933287d2016-01-30 13:46:54 -0500425int orangefs_permission(struct inode *inode, int mask)
426{
427 int ret;
428
429 if (mask & MAY_NOT_BLOCK)
430 return -ECHILD;
431
432 gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);
433
434 /* Make sure the permission (and other common attrs) are up to date. */
Martin Brandenburg8b607852018-02-07 18:44:50 +0000435 ret = orangefs_inode_getattr(inode, 0);
Martin Brandenburg933287d2016-01-30 13:46:54 -0500436 if (ret < 0)
437 return ret;
438
439 return generic_permission(inode, mask);
440}
441
Deepa Dinamani95582b02018-05-08 19:36:02 -0700442int orangefs_update_time(struct inode *inode, struct timespec64 *time, int flags)
Martin Brandenburga55f2d82017-11-07 15:01:40 -0500443{
444 struct iattr iattr;
445 gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_update_time: %pU\n",
446 get_khandle_from_ino(inode));
447 generic_update_time(inode, time, flags);
448 memset(&iattr, 0, sizeof iattr);
449 if (flags & S_ATIME)
450 iattr.ia_valid |= ATTR_ATIME;
451 if (flags & S_CTIME)
452 iattr.ia_valid |= ATTR_CTIME;
453 if (flags & S_MTIME)
454 iattr.ia_valid |= ATTR_MTIME;
Martin Brandenburgafd9fb22018-02-13 20:13:46 +0000455 return __orangefs_setattr(inode, &iattr);
Martin Brandenburga55f2d82017-11-07 15:01:40 -0500456}
457
Mike Marshall95f5f882018-05-11 17:11:48 -0400458/* ORANGEFS2 implementation of VFS inode operations for files */
Martin Brandenburgbdd6f082018-04-03 16:27:13 +0000459static const struct inode_operations orangefs_file_inode_operations = {
Yi Liu8bb8aef2015-11-24 15:12:14 -0500460 .get_acl = orangefs_get_acl,
461 .set_acl = orangefs_set_acl,
462 .setattr = orangefs_setattr,
463 .getattr = orangefs_getattr,
Yi Liu8bb8aef2015-11-24 15:12:14 -0500464 .listxattr = orangefs_listxattr,
Martin Brandenburg933287d2016-01-30 13:46:54 -0500465 .permission = orangefs_permission,
Martin Brandenburga55f2d82017-11-07 15:01:40 -0500466 .update_time = orangefs_update_time,
Mike Marshall5db11c22015-07-17 10:38:12 -0400467};
468
Yi Liu8bb8aef2015-11-24 15:12:14 -0500469static int orangefs_init_iops(struct inode *inode)
Mike Marshall5db11c22015-07-17 10:38:12 -0400470{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500471 inode->i_mapping->a_ops = &orangefs_address_operations;
Mike Marshall5db11c22015-07-17 10:38:12 -0400472
473 switch (inode->i_mode & S_IFMT) {
474 case S_IFREG:
Yi Liu8bb8aef2015-11-24 15:12:14 -0500475 inode->i_op = &orangefs_file_inode_operations;
476 inode->i_fop = &orangefs_file_operations;
Mike Marshall5db11c22015-07-17 10:38:12 -0400477 break;
478 case S_IFLNK:
Yi Liu8bb8aef2015-11-24 15:12:14 -0500479 inode->i_op = &orangefs_symlink_inode_operations;
Mike Marshall5db11c22015-07-17 10:38:12 -0400480 break;
481 case S_IFDIR:
Yi Liu8bb8aef2015-11-24 15:12:14 -0500482 inode->i_op = &orangefs_dir_inode_operations;
483 inode->i_fop = &orangefs_dir_operations;
Mike Marshall5db11c22015-07-17 10:38:12 -0400484 break;
485 default:
486 gossip_debug(GOSSIP_INODE_DEBUG,
487 "%s: unsupported mode\n",
488 __func__);
489 return -EINVAL;
490 }
491
492 return 0;
493}
494
495/*
Mike Marshall95f5f882018-05-11 17:11:48 -0400496 * Given an ORANGEFS object identifier (fsid, handle), convert it into
497 * a ino_t type that will be used as a hash-index from where the handle will
Mike Marshall5db11c22015-07-17 10:38:12 -0400498 * be searched for in the VFS hash table of inodes.
499 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500500static inline ino_t orangefs_handle_hash(struct orangefs_object_kref *ref)
Mike Marshall5db11c22015-07-17 10:38:12 -0400501{
502 if (!ref)
503 return 0;
Yi Liu8bb8aef2015-11-24 15:12:14 -0500504 return orangefs_khandle_to_ino(&(ref->khandle));
Mike Marshall5db11c22015-07-17 10:38:12 -0400505}
506
507/*
508 * Called to set up an inode from iget5_locked.
509 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500510static int orangefs_set_inode(struct inode *inode, void *data)
Mike Marshall5db11c22015-07-17 10:38:12 -0400511{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500512 struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
Martin Brandenburga4c680a2016-03-16 14:35:21 -0400513 ORANGEFS_I(inode)->refn.fs_id = ref->fs_id;
514 ORANGEFS_I(inode)->refn.khandle = ref->khandle;
Martin Brandenburgafd9fb22018-02-13 20:13:46 +0000515 ORANGEFS_I(inode)->attr_valid = 0;
Martin Brandenburgfc2e2e92017-12-12 13:46:30 -0500516 hash_init(ORANGEFS_I(inode)->xattr_cache);
Mike Marshall5db11c22015-07-17 10:38:12 -0400517 return 0;
518}
519
520/*
521 * Called to determine if handles match.
522 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500523static int orangefs_test_inode(struct inode *inode, void *data)
Mike Marshall5db11c22015-07-17 10:38:12 -0400524{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500525 struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
526 struct orangefs_inode_s *orangefs_inode = NULL;
Mike Marshall5db11c22015-07-17 10:38:12 -0400527
Yi Liu8bb8aef2015-11-24 15:12:14 -0500528 orangefs_inode = ORANGEFS_I(inode);
Mike Marshall95f5f882018-05-11 17:11:48 -0400529 /* test handles and fs_ids... */
530 return (!ORANGEFS_khandle_cmp(&(orangefs_inode->refn.khandle),
531 &(ref->khandle)) &&
532 orangefs_inode->refn.fs_id == ref->fs_id);
Mike Marshall5db11c22015-07-17 10:38:12 -0400533}
534
535/*
Yi Liu8bb8aef2015-11-24 15:12:14 -0500536 * Front-end to lookup the inode-cache maintained by the VFS using the ORANGEFS
Mike Marshall5db11c22015-07-17 10:38:12 -0400537 * file handle.
538 *
539 * @sb: the file system super block instance.
Mike Marshall95f5f882018-05-11 17:11:48 -0400540 * @ref: The ORANGEFS object for which we are trying to locate an inode.
Mike Marshall5db11c22015-07-17 10:38:12 -0400541 */
Mike Marshall95f5f882018-05-11 17:11:48 -0400542struct inode *orangefs_iget(struct super_block *sb,
543 struct orangefs_object_kref *ref)
Mike Marshall5db11c22015-07-17 10:38:12 -0400544{
545 struct inode *inode = NULL;
546 unsigned long hash;
547 int error;
548
Yi Liu8bb8aef2015-11-24 15:12:14 -0500549 hash = orangefs_handle_hash(ref);
Mike Marshall95f5f882018-05-11 17:11:48 -0400550 inode = iget5_locked(sb,
551 hash,
552 orangefs_test_inode,
553 orangefs_set_inode,
554 ref);
Mike Marshallb5d72cd2018-10-18 13:52:23 -0400555
556 if (!inode)
557 return ERR_PTR(-ENOMEM);
558
559 if (!(inode->i_state & I_NEW))
Mike Marshall5db11c22015-07-17 10:38:12 -0400560 return inode;
561
Martin Brandenburg8b607852018-02-07 18:44:50 +0000562 error = orangefs_inode_getattr(inode, ORANGEFS_GETATTR_NEW);
Mike Marshall5db11c22015-07-17 10:38:12 -0400563 if (error) {
564 iget_failed(inode);
565 return ERR_PTR(error);
566 }
567
568 inode->i_ino = hash; /* needed for stat etc */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500569 orangefs_init_iops(inode);
Mike Marshall5db11c22015-07-17 10:38:12 -0400570 unlock_new_inode(inode);
571
572 gossip_debug(GOSSIP_INODE_DEBUG,
573 "iget handle %pU, fsid %d hash %ld i_ino %lu\n",
574 &ref->khandle,
575 ref->fs_id,
576 hash,
577 inode->i_ino);
578
579 return inode;
580}
581
582/*
583 * Allocate an inode for a newly created file and insert it into the inode hash.
584 */
Yi Liu8bb8aef2015-11-24 15:12:14 -0500585struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
586 int mode, dev_t dev, struct orangefs_object_kref *ref)
Mike Marshall5db11c22015-07-17 10:38:12 -0400587{
Yi Liu8bb8aef2015-11-24 15:12:14 -0500588 unsigned long hash = orangefs_handle_hash(ref);
Mike Marshall5db11c22015-07-17 10:38:12 -0400589 struct inode *inode;
590 int error;
591
592 gossip_debug(GOSSIP_INODE_DEBUG,
Mike Marshall52534872016-02-16 17:09:09 -0500593 "%s:(sb is %p | MAJOR(dev)=%u | MINOR(dev)=%u mode=%o)\n",
594 __func__,
Mike Marshall5db11c22015-07-17 10:38:12 -0400595 sb,
596 MAJOR(dev),
597 MINOR(dev),
598 mode);
599
600 inode = new_inode(sb);
601 if (!inode)
Mike Marshall56249992018-10-18 13:47:16 -0400602 return ERR_PTR(-ENOMEM);
Mike Marshall5db11c22015-07-17 10:38:12 -0400603
Yi Liu8bb8aef2015-11-24 15:12:14 -0500604 orangefs_set_inode(inode, ref);
Mike Marshall5db11c22015-07-17 10:38:12 -0400605 inode->i_ino = hash; /* needed for stat etc */
606
Martin Brandenburg8b607852018-02-07 18:44:50 +0000607 error = orangefs_inode_getattr(inode, ORANGEFS_GETATTR_NEW);
Mike Marshall5db11c22015-07-17 10:38:12 -0400608 if (error)
609 goto out_iput;
610
Yi Liu8bb8aef2015-11-24 15:12:14 -0500611 orangefs_init_iops(inode);
Mike Marshall5db11c22015-07-17 10:38:12 -0400612 inode->i_rdev = dev;
613
Yi Liu8bb8aef2015-11-24 15:12:14 -0500614 error = insert_inode_locked4(inode, hash, orangefs_test_inode, ref);
Mike Marshall5db11c22015-07-17 10:38:12 -0400615 if (error < 0)
616 goto out_iput;
617
618 gossip_debug(GOSSIP_INODE_DEBUG,
619 "Initializing ACL's for inode %pU\n",
620 get_khandle_from_ino(inode));
Yi Liu8bb8aef2015-11-24 15:12:14 -0500621 orangefs_init_acl(inode, dir);
Mike Marshall5db11c22015-07-17 10:38:12 -0400622 return inode;
623
624out_iput:
625 iput(inode);
626 return ERR_PTR(error);
627}