orangefs: implement writepages
[linux-block.git] / fs / orangefs / inode.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
5db11c21
MM
2/*
3 * (C) 2001 Clemson University and The University of Chicago
afd9fb2a 4 * Copyright 2018 Omnibond Systems, L.L.C.
5db11c21
MM
5 *
6 * See COPYING in top-level directory.
7 */
8
9/*
10 * Linux VFS inode operations.
11 */
12
2f8b5444 13#include <linux/bvec.h>
5db11c21 14#include "protocol.h"
575e9461
MM
15#include "orangefs-kernel.h"
16#include "orangefs-bufmap.h"
5db11c21 17
52e2d0a3
MB
18static int orangefs_writepage_locked(struct page *page,
19 struct writeback_control *wbc)
85ac799c
MB
20{
21 struct inode *inode = page->mapping->host;
52e2d0a3 22 struct orangefs_write_range *wr = NULL;
85ac799c
MB
23 struct iov_iter iter;
24 struct bio_vec bv;
25 size_t len, wlen;
26 ssize_t ret;
27 loff_t off;
28
29 set_page_writeback(page);
30
85ac799c 31 len = i_size_read(inode);
52e2d0a3
MB
32 if (PagePrivate(page)) {
33 wr = (struct orangefs_write_range *)page_private(page);
34 off = wr->pos;
35 if (off + wr->len > len)
36 wlen = len - off;
37 else
38 wlen = wr->len;
39 } else {
40 WARN_ON(1);
41 off = page_offset(page);
42 if (off + PAGE_SIZE > len)
43 wlen = len - off;
44 else
45 wlen = PAGE_SIZE;
85ac799c 46 }
52e2d0a3
MB
47 /* Should've been handled in orangefs_invalidatepage. */
48 WARN_ON(off == len || off + wlen > len);
85ac799c
MB
49
50 bv.bv_page = page;
51 bv.bv_len = wlen;
52 bv.bv_offset = off % PAGE_SIZE;
52e2d0a3 53 WARN_ON(wlen == 0);
85ac799c
MB
54 iov_iter_bvec(&iter, WRITE, &bv, 1, wlen);
55
56 ret = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, wlen,
52e2d0a3 57 len, wr);
85ac799c
MB
58 if (ret < 0) {
59 SetPageError(page);
60 mapping_set_error(page->mapping, ret);
61 } else {
62 ret = 0;
63 }
52e2d0a3
MB
64 if (wr) {
65 kfree(wr);
66 set_page_private(page, 0);
67 ClearPagePrivate(page);
68 put_page(page);
69 }
70 return ret;
71}
72
73static int orangefs_writepage(struct page *page, struct writeback_control *wbc)
74{
75 int ret;
76 ret = orangefs_writepage_locked(page, wbc);
85ac799c
MB
77 unlock_page(page);
78 end_page_writeback(page);
79 return ret;
80}
81
a68d9c60 82static int orangefs_readpage(struct file *file, struct page *page)
5db11c21 83{
5db11c21 84 struct inode *inode = page->mapping->host;
c453dcfc
MB
85 struct iov_iter iter;
86 struct bio_vec bv;
87 ssize_t ret;
88 loff_t off;
89
90 off = page_offset(page);
91 bv.bv_page = page;
92 bv.bv_len = PAGE_SIZE;
93 bv.bv_offset = 0;
94 iov_iter_bvec(&iter, READ, &bv, 1, PAGE_SIZE);
95
96 ret = wait_for_direct_io(ORANGEFS_IO_READ, inode, &off, &iter,
52e2d0a3 97 PAGE_SIZE, inode->i_size, NULL);
74f68fce 98 /* this will only zero remaining unread portions of the page data */
c453dcfc 99 iov_iter_zero(~0U, &iter);
5db11c21
MM
100 /* takes care of potential aliasing */
101 flush_dcache_page(page);
c453dcfc 102 if (ret < 0) {
5db11c21
MM
103 SetPageError(page);
104 } else {
105 SetPageUptodate(page);
106 if (PageError(page))
107 ClearPageError(page);
108 ret = 0;
109 }
5db11c21
MM
110 /* unlock the page after the ->readpage() routine completes */
111 unlock_page(page);
112 return ret;
113}
114
52e2d0a3
MB
115static int orangefs_launder_page(struct page *);
116
117static int orangefs_write_begin(struct file *file,
118 struct address_space *mapping,
119 loff_t pos, unsigned len, unsigned flags, struct page **pagep,
120 void **fsdata)
121{
122 struct orangefs_write_range *wr;
123 struct page *page;
124 pgoff_t index;
125 int ret;
126
127 index = pos >> PAGE_SHIFT;
128
129 page = grab_cache_page_write_begin(mapping, index, flags);
130 if (!page)
131 return -ENOMEM;
132
133 *pagep = page;
134
135 if (PageDirty(page) && !PagePrivate(page)) {
136 /*
137 * Should be impossible. If it happens, launder the page
138 * since we don't know what's dirty. This will WARN in
139 * orangefs_writepage_locked.
140 */
141 ret = orangefs_launder_page(page);
142 if (ret)
143 return ret;
144 }
145 if (PagePrivate(page)) {
146 struct orangefs_write_range *wr;
147 wr = (struct orangefs_write_range *)page_private(page);
148 if (wr->pos + wr->len == pos &&
149 uid_eq(wr->uid, current_fsuid()) &&
150 gid_eq(wr->gid, current_fsgid())) {
151 wr->len += len;
152 goto okay;
153 } else {
154 ret = orangefs_launder_page(page);
155 if (ret)
156 return ret;
157 }
158
159 }
160
161 wr = kmalloc(sizeof *wr, GFP_KERNEL);
162 if (!wr)
163 return -ENOMEM;
164
165 wr->pos = pos;
166 wr->len = len;
167 wr->uid = current_fsuid();
168 wr->gid = current_fsgid();
169 SetPagePrivate(page);
170 set_page_private(page, (unsigned long)wr);
171 get_page(page);
172okay:
173
174 if (!PageUptodate(page) && (len != PAGE_SIZE)) {
175 unsigned from = pos & (PAGE_SIZE - 1);
176
177 zero_user_segments(page, 0, from, from + len, PAGE_SIZE);
178 }
179 return 0;
180}
181
85ac799c
MB
182static int orangefs_write_end(struct file *file, struct address_space *mapping,
183 loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata)
184{
185 int r;
186 r = simple_write_end(file, mapping, pos, len, copied, page, fsdata);
187 mark_inode_dirty_sync(file_inode(file));
188 return r;
189}
190
8bb8aefd 191static void orangefs_invalidatepage(struct page *page,
5db11c21
MM
192 unsigned int offset,
193 unsigned int length)
194{
52e2d0a3
MB
195 struct orangefs_write_range *wr;
196 wr = (struct orangefs_write_range *)page_private(page);
197
198 if (offset == 0 && length == PAGE_SIZE) {
199 kfree((struct orangefs_write_range *)page_private(page));
200 set_page_private(page, 0);
201 ClearPagePrivate(page);
202 put_page(page);
203 /* write range entirely within invalidate range (or equal) */
204 } else if (page_offset(page) + offset <= wr->pos &&
205 wr->pos + wr->len <= page_offset(page) + offset + length) {
206 kfree((struct orangefs_write_range *)page_private(page));
207 set_page_private(page, 0);
208 ClearPagePrivate(page);
209 put_page(page);
210 /* XXX is this right? only caller in fs */
211 cancel_dirty_page(page);
212 /* invalidate range chops off end of write range */
213 } else if (wr->pos < page_offset(page) + offset &&
214 wr->pos + wr->len <= page_offset(page) + offset + length &&
215 page_offset(page) + offset < wr->pos + wr->len) {
216 size_t x;
217 x = wr->pos + wr->len - (page_offset(page) + offset);
218 WARN_ON(x > wr->len);
219 wr->len -= x;
220 wr->uid = current_fsuid();
221 wr->gid = current_fsgid();
222 /* invalidate range chops off beginning of write range */
223 } else if (page_offset(page) + offset <= wr->pos &&
224 page_offset(page) + offset + length < wr->pos + wr->len &&
225 wr->pos < page_offset(page) + offset + length) {
226 size_t x;
227 x = page_offset(page) + offset + length - wr->pos;
228 WARN_ON(x > wr->len);
229 wr->pos += x;
230 wr->len -= x;
231 wr->uid = current_fsuid();
232 wr->gid = current_fsgid();
233 /* invalidate range entirely within write range (punch hole) */
234 } else if (wr->pos < page_offset(page) + offset &&
235 page_offset(page) + offset + length < wr->pos + wr->len) {
236 /* XXX what do we do here... should not WARN_ON */
237 WARN_ON(1);
238 /* punch hole */
239 /*
240 * should we just ignore this and write it out anyway?
241 * it hardly makes sense
242 */
243 /* non-overlapping ranges */
244 } else {
245 /* WARN if they do overlap */
246 if (!((page_offset(page) + offset + length <= wr->pos) ^
247 (wr->pos + wr->len <= page_offset(page) + offset))) {
248 WARN_ON(1);
249 printk("invalidate range offset %llu length %u\n",
250 page_offset(page) + offset, length);
251 printk("write range offset %llu length %zu\n",
252 wr->pos, wr->len);
253 }
254 }
255}
5db11c21 256
52e2d0a3
MB
257static int orangefs_releasepage(struct page *page, gfp_t foo)
258{
259 return !PagePrivate(page);
260}
5db11c21 261
52e2d0a3
MB
262static void orangefs_freepage(struct page *page)
263{
264 if (PagePrivate(page)) {
265 kfree((struct orangefs_write_range *)page_private(page));
266 set_page_private(page, 0);
267 ClearPagePrivate(page);
268 put_page(page);
269 }
5db11c21
MM
270}
271
52e2d0a3 272static int orangefs_launder_page(struct page *page)
5db11c21 273{
52e2d0a3
MB
274 int r = 0;
275 struct writeback_control wbc = {
276 .sync_mode = WB_SYNC_ALL,
277 .nr_to_write = 0,
278 };
279 wait_on_page_writeback(page);
280 if (clear_page_dirty_for_io(page)) {
281 r = orangefs_writepage_locked(page, &wbc);
282 end_page_writeback(page);
283 }
284 return r;
5db11c21
MM
285}
286
3903f150
MM
287static ssize_t orangefs_direct_IO(struct kiocb *iocb,
288 struct iov_iter *iter)
289{
3e9dfc6e
MB
290 /*
291 * Comment from original do_readv_writev:
292 * Common entry point for read/write/readv/writev
293 * This function will dispatch it to either the direct I/O
294 * or buffered I/O path depending on the mount options and/or
295 * augmented/extended metadata attached to the file.
296 * Note: File extended attributes override any mount options.
297 */
c453dcfc 298 struct file *file = iocb->ki_filp;
3e9dfc6e
MB
299 loff_t pos = iocb->ki_pos;
300 enum ORANGEFS_io_type type = iov_iter_rw(iter) == WRITE ?
301 ORANGEFS_IO_WRITE : ORANGEFS_IO_READ;
302 loff_t *offset = &pos;
303 struct inode *inode = file->f_mapping->host;
304 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
305 struct orangefs_khandle *handle = &orangefs_inode->refn.khandle;
306 size_t count = iov_iter_count(iter);
3e9dfc6e
MB
307 ssize_t total_count = 0;
308 ssize_t ret = -EINVAL;
309 int i = 0;
310
311 gossip_debug(GOSSIP_FILE_DEBUG,
312 "%s-BEGIN(%pU): count(%d) after estimate_max_iovecs.\n",
313 __func__,
314 handle,
315 (int)count);
316
317 if (type == ORANGEFS_IO_WRITE) {
318 gossip_debug(GOSSIP_FILE_DEBUG,
319 "%s(%pU): proceeding with offset : %llu, "
320 "size %d\n",
321 __func__,
322 handle,
323 llu(*offset),
324 (int)count);
325 }
326
327 if (count == 0) {
328 ret = 0;
329 goto out;
330 }
331
332 while (iov_iter_count(iter)) {
333 size_t each_count = iov_iter_count(iter);
334 size_t amt_complete;
335 i++;
336
337 /* how much to transfer in this loop iteration */
338 if (each_count > orangefs_bufmap_size_query())
339 each_count = orangefs_bufmap_size_query();
340
341 gossip_debug(GOSSIP_FILE_DEBUG,
342 "%s(%pU): size of each_count(%d)\n",
343 __func__,
344 handle,
345 (int)each_count);
346 gossip_debug(GOSSIP_FILE_DEBUG,
347 "%s(%pU): BEFORE wait_for_io: offset is %d\n",
348 __func__,
349 handle,
350 (int)*offset);
351
352 ret = wait_for_direct_io(type, inode, offset, iter,
52e2d0a3 353 each_count, 0, NULL);
3e9dfc6e
MB
354 gossip_debug(GOSSIP_FILE_DEBUG,
355 "%s(%pU): return from wait_for_io:%d\n",
356 __func__,
357 handle,
358 (int)ret);
359
360 if (ret < 0)
361 goto out;
362
363 *offset += ret;
364 total_count += ret;
365 amt_complete = ret;
366
367 gossip_debug(GOSSIP_FILE_DEBUG,
368 "%s(%pU): AFTER wait_for_io: offset is %d\n",
369 __func__,
370 handle,
371 (int)*offset);
372
373 /*
374 * if we got a short I/O operations,
375 * fall out and return what we got so far
376 */
377 if (amt_complete < each_count)
378 break;
379 } /*end while */
380
381out:
382 if (total_count > 0)
383 ret = total_count;
384 if (ret > 0) {
385 if (type == ORANGEFS_IO_READ) {
386 file_accessed(file);
387 } else {
388 file_update_time(file);
389 if (*offset > i_size_read(inode))
390 i_size_write(inode, *offset);
391 }
392 }
393
394 gossip_debug(GOSSIP_FILE_DEBUG,
395 "%s(%pU): Value(%d) returned.\n",
396 __func__,
397 handle,
398 (int)ret);
399
400 return ret;
3903f150 401}
5db11c21 402
8bb8aefd 403/** ORANGEFS2 implementation of address space operations */
bdd6f083 404static const struct address_space_operations orangefs_address_operations = {
85ac799c 405 .writepage = orangefs_writepage,
8bb8aefd 406 .readpage = orangefs_readpage,
85ac799c 407 .set_page_dirty = __set_page_dirty_nobuffers,
52e2d0a3 408 .write_begin = orangefs_write_begin,
85ac799c 409 .write_end = orangefs_write_end,
8bb8aefd
YL
410 .invalidatepage = orangefs_invalidatepage,
411 .releasepage = orangefs_releasepage,
52e2d0a3
MB
412 .freepage = orangefs_freepage,
413 .launder_page = orangefs_launder_page,
3903f150 414 .direct_IO = orangefs_direct_IO,
5db11c21
MM
415};
416
52e2d0a3
MB
417vm_fault_t orangefs_page_mkwrite(struct vm_fault *vmf)
418{
419 struct page *page = vmf->page;
420 struct inode *inode = file_inode(vmf->vma->vm_file);
421 vm_fault_t ret = VM_FAULT_LOCKED;
422 struct orangefs_write_range *wr;
423
424 lock_page(page);
425 if (PageDirty(page) && !PagePrivate(page)) {
426 /*
427 * Should be impossible. If it happens, launder the page
428 * since we don't know what's dirty. This will WARN in
429 * orangefs_writepage_locked.
430 */
431 if (orangefs_launder_page(page)) {
432 ret = VM_FAULT_RETRY;
433 goto out;
434 }
435 }
436 if (PagePrivate(page)) {
437 wr = (struct orangefs_write_range *)page_private(page);
438 if (uid_eq(wr->uid, current_fsuid()) &&
439 gid_eq(wr->gid, current_fsgid())) {
440 wr->pos = page_offset(page);
441 wr->len = PAGE_SIZE;
442 goto okay;
443 } else {
444 if (orangefs_launder_page(page)) {
445 ret = VM_FAULT_RETRY;
446 goto out;
447 }
448 }
449 }
450 wr = kmalloc(sizeof *wr, GFP_KERNEL);
451 if (!wr) {
452 ret = VM_FAULT_RETRY;
453 goto out;
454 }
455 wr->pos = page_offset(page);
456 wr->len = PAGE_SIZE;
457 wr->uid = current_fsuid();
458 wr->gid = current_fsgid();
459 SetPagePrivate(page);
460 set_page_private(page, (unsigned long)wr);
461 get_page(page);
462okay:
463
464 sb_start_pagefault(inode->i_sb);
465 file_update_time(vmf->vma->vm_file);
466 if (page->mapping != inode->i_mapping) {
467 unlock_page(page);
468 ret = VM_FAULT_NOPAGE;
469 goto out;
470 }
471
472 /*
473 * We mark the page dirty already here so that when freeze is in
474 * progress, we are guaranteed that writeback during freezing will
475 * see the dirty page and writeprotect it again.
476 */
477 set_page_dirty(page);
478 wait_for_stable_page(page);
479out:
480 sb_end_pagefault(inode->i_sb);
481 return ret;
482}
483
8bb8aefd 484static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
5db11c21 485{
8bb8aefd
YL
486 struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
487 struct orangefs_kernel_op_s *new_op;
fecd86aa 488 loff_t orig_size;
5db11c21
MM
489 int ret = -EINVAL;
490
491 gossip_debug(GOSSIP_INODE_DEBUG,
492 "%s: %pU: Handle is %pU | fs_id %d | size is %llu\n",
493 __func__,
494 get_khandle_from_ino(inode),
8bb8aefd
YL
495 &orangefs_inode->refn.khandle,
496 orangefs_inode->refn.fs_id,
5db11c21
MM
497 iattr->ia_size);
498
fecd86aa 499 /* Ensure that we have a up to date size, so we know if it changed. */
8b60785c 500 ret = orangefs_inode_getattr(inode, ORANGEFS_GETATTR_SIZE);
fecd86aa
MB
501 if (ret == -ESTALE)
502 ret = -EIO;
503 if (ret) {
504 gossip_err("%s: orangefs_inode_getattr failed, ret:%d:.\n",
505 __func__, ret);
506 return ret;
507 }
508 orig_size = i_size_read(inode);
509
5db11c21
MM
510 truncate_setsize(inode, iattr->ia_size);
511
8bb8aefd 512 new_op = op_alloc(ORANGEFS_VFS_OP_TRUNCATE);
5db11c21
MM
513 if (!new_op)
514 return -ENOMEM;
515
8bb8aefd 516 new_op->upcall.req.truncate.refn = orangefs_inode->refn;
5db11c21
MM
517 new_op->upcall.req.truncate.size = (__s64) iattr->ia_size;
518
95f5f88f
MM
519 ret = service_operation(new_op,
520 __func__,
521 get_interruptible_flag(inode));
5db11c21
MM
522
523 /*
524 * the truncate has no downcall members to retrieve, but
525 * the status value tells us if it went through ok or not
526 */
95f5f88f 527 gossip_debug(GOSSIP_INODE_DEBUG, "%s: ret:%d:\n", __func__, ret);
5db11c21
MM
528
529 op_release(new_op);
530
531 if (ret != 0)
532 return ret;
533
f83140c1 534 if (orig_size != i_size_read(inode))
5db11c21 535 iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
5db11c21
MM
536
537 return ret;
538}
539
afd9fb2a 540int __orangefs_setattr(struct inode *inode, struct iattr *iattr)
5db11c21 541{
df2d7337 542 int ret;
5db11c21 543
afd9fb2a
MB
544 if (iattr->ia_valid & ATTR_MODE) {
545 if (iattr->ia_mode & (S_ISVTX)) {
546 if (is_root_handle(inode)) {
547 /*
548 * allow sticky bit to be set on root (since
549 * it shows up that way by default anyhow),
550 * but don't show it to the server
551 */
552 iattr->ia_mode -= S_ISVTX;
553 } else {
554 gossip_debug(GOSSIP_UTILS_DEBUG,
555 "User attempted to set sticky bit on non-root directory; returning EINVAL.\n");
556 return -EINVAL;
557 }
558 }
559 if (iattr->ia_mode & (S_ISUID)) {
560 gossip_debug(GOSSIP_UTILS_DEBUG,
561 "Attempting to set setuid bit (not supported); returning EINVAL.\n");
562 return -EINVAL;
563 }
564 }
5db11c21 565
53950ef5 566 if (iattr->ia_valid & ATTR_SIZE) {
8bb8aefd 567 ret = orangefs_setattr_size(inode, iattr);
5db11c21
MM
568 if (ret)
569 goto out;
570 }
571
afd9fb2a
MB
572again:
573 spin_lock(&inode->i_lock);
574 if (ORANGEFS_I(inode)->attr_valid) {
575 if (uid_eq(ORANGEFS_I(inode)->attr_uid, current_fsuid()) &&
576 gid_eq(ORANGEFS_I(inode)->attr_gid, current_fsgid())) {
577 ORANGEFS_I(inode)->attr_valid = iattr->ia_valid;
578 } else {
579 spin_unlock(&inode->i_lock);
580 write_inode_now(inode, 1);
581 goto again;
582 }
583 } else {
584 ORANGEFS_I(inode)->attr_valid = iattr->ia_valid;
585 ORANGEFS_I(inode)->attr_uid = current_fsuid();
586 ORANGEFS_I(inode)->attr_gid = current_fsgid();
587 }
5db11c21 588 setattr_copy(inode, iattr);
afd9fb2a 589 spin_unlock(&inode->i_lock);
5db11c21
MM
590 mark_inode_dirty(inode);
591
df2d7337 592 if (iattr->ia_valid & ATTR_MODE)
5db11c21
MM
593 /* change mod on a file that has ACLs */
594 ret = posix_acl_chmod(inode, inode->i_mode);
595
df2d7337 596 ret = 0;
5db11c21 597out:
afd9fb2a
MB
598 return ret;
599}
600
601/*
602 * Change attributes of an object referenced by dentry.
603 */
604int orangefs_setattr(struct dentry *dentry, struct iattr *iattr)
605{
606 int ret;
607 gossip_debug(GOSSIP_INODE_DEBUG, "__orangefs_setattr: called on %pd\n",
608 dentry);
609 ret = setattr_prepare(dentry, iattr);
610 if (ret)
611 goto out;
612 ret = __orangefs_setattr(d_inode(dentry), iattr);
613 sync_inode_metadata(d_inode(dentry), 1);
614out:
615 gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_setattr: returning %d\n",
616 ret);
5db11c21
MM
617 return ret;
618}
619
620/*
621 * Obtain attributes of an object given a dentry
622 */
a528d35e
DH
623int orangefs_getattr(const struct path *path, struct kstat *stat,
624 u32 request_mask, unsigned int flags)
5db11c21
MM
625{
626 int ret = -ENOENT;
a528d35e 627 struct inode *inode = path->dentry->d_inode;
5db11c21
MM
628
629 gossip_debug(GOSSIP_INODE_DEBUG,
5e4f606e
MB
630 "orangefs_getattr: called on %pd mask %u\n",
631 path->dentry, request_mask);
5db11c21 632
8b60785c
MB
633 ret = orangefs_inode_getattr(inode,
634 request_mask & STATX_SIZE ? ORANGEFS_GETATTR_SIZE : 0);
5db11c21 635 if (ret == 0) {
a528d35e 636 generic_fillattr(inode, stat);
a7d3e78a 637
5db11c21 638 /* override block size reported to stat */
5678b5d6
CH
639 if (!(request_mask & STATX_SIZE))
640 stat->result_mask &= ~STATX_SIZE;
7f54910f
MB
641
642 stat->attributes_mask = STATX_ATTR_IMMUTABLE |
643 STATX_ATTR_APPEND;
644 if (inode->i_flags & S_IMMUTABLE)
645 stat->attributes |= STATX_ATTR_IMMUTABLE;
646 if (inode->i_flags & S_APPEND)
647 stat->attributes |= STATX_ATTR_APPEND;
5db11c21
MM
648 }
649 return ret;
650}
651
933287da
MB
652int orangefs_permission(struct inode *inode, int mask)
653{
654 int ret;
655
656 if (mask & MAY_NOT_BLOCK)
657 return -ECHILD;
658
659 gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);
660
661 /* Make sure the permission (and other common attrs) are up to date. */
8b60785c 662 ret = orangefs_inode_getattr(inode, 0);
933287da
MB
663 if (ret < 0)
664 return ret;
665
666 return generic_permission(inode, mask);
667}
668
95582b00 669int orangefs_update_time(struct inode *inode, struct timespec64 *time, int flags)
a55f2d86
MB
670{
671 struct iattr iattr;
672 gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_update_time: %pU\n",
673 get_khandle_from_ino(inode));
674 generic_update_time(inode, time, flags);
675 memset(&iattr, 0, sizeof iattr);
676 if (flags & S_ATIME)
677 iattr.ia_valid |= ATTR_ATIME;
678 if (flags & S_CTIME)
679 iattr.ia_valid |= ATTR_CTIME;
680 if (flags & S_MTIME)
681 iattr.ia_valid |= ATTR_MTIME;
afd9fb2a 682 return __orangefs_setattr(inode, &iattr);
a55f2d86
MB
683}
684
95f5f88f 685/* ORANGEFS2 implementation of VFS inode operations for files */
bdd6f083 686static const struct inode_operations orangefs_file_inode_operations = {
8bb8aefd
YL
687 .get_acl = orangefs_get_acl,
688 .set_acl = orangefs_set_acl,
689 .setattr = orangefs_setattr,
690 .getattr = orangefs_getattr,
8bb8aefd 691 .listxattr = orangefs_listxattr,
933287da 692 .permission = orangefs_permission,
a55f2d86 693 .update_time = orangefs_update_time,
5db11c21
MM
694};
695
8bb8aefd 696static int orangefs_init_iops(struct inode *inode)
5db11c21 697{
8bb8aefd 698 inode->i_mapping->a_ops = &orangefs_address_operations;
5db11c21
MM
699
700 switch (inode->i_mode & S_IFMT) {
701 case S_IFREG:
8bb8aefd
YL
702 inode->i_op = &orangefs_file_inode_operations;
703 inode->i_fop = &orangefs_file_operations;
5db11c21
MM
704 break;
705 case S_IFLNK:
8bb8aefd 706 inode->i_op = &orangefs_symlink_inode_operations;
5db11c21
MM
707 break;
708 case S_IFDIR:
8bb8aefd
YL
709 inode->i_op = &orangefs_dir_inode_operations;
710 inode->i_fop = &orangefs_dir_operations;
5db11c21
MM
711 break;
712 default:
713 gossip_debug(GOSSIP_INODE_DEBUG,
714 "%s: unsupported mode\n",
715 __func__);
716 return -EINVAL;
717 }
718
719 return 0;
720}
721
722/*
95f5f88f
MM
723 * Given an ORANGEFS object identifier (fsid, handle), convert it into
724 * a ino_t type that will be used as a hash-index from where the handle will
5db11c21
MM
725 * be searched for in the VFS hash table of inodes.
726 */
8bb8aefd 727static inline ino_t orangefs_handle_hash(struct orangefs_object_kref *ref)
5db11c21
MM
728{
729 if (!ref)
730 return 0;
8bb8aefd 731 return orangefs_khandle_to_ino(&(ref->khandle));
5db11c21
MM
732}
733
734/*
735 * Called to set up an inode from iget5_locked.
736 */
8bb8aefd 737static int orangefs_set_inode(struct inode *inode, void *data)
5db11c21 738{
8bb8aefd 739 struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
a4c680a0
MB
740 ORANGEFS_I(inode)->refn.fs_id = ref->fs_id;
741 ORANGEFS_I(inode)->refn.khandle = ref->khandle;
afd9fb2a 742 ORANGEFS_I(inode)->attr_valid = 0;
fc2e2e9c 743 hash_init(ORANGEFS_I(inode)->xattr_cache);
5db11c21
MM
744 return 0;
745}
746
747/*
748 * Called to determine if handles match.
749 */
8bb8aefd 750static int orangefs_test_inode(struct inode *inode, void *data)
5db11c21 751{
8bb8aefd
YL
752 struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
753 struct orangefs_inode_s *orangefs_inode = NULL;
5db11c21 754
8bb8aefd 755 orangefs_inode = ORANGEFS_I(inode);
95f5f88f
MM
756 /* test handles and fs_ids... */
757 return (!ORANGEFS_khandle_cmp(&(orangefs_inode->refn.khandle),
758 &(ref->khandle)) &&
759 orangefs_inode->refn.fs_id == ref->fs_id);
5db11c21
MM
760}
761
762/*
8bb8aefd 763 * Front-end to lookup the inode-cache maintained by the VFS using the ORANGEFS
5db11c21
MM
764 * file handle.
765 *
766 * @sb: the file system super block instance.
95f5f88f 767 * @ref: The ORANGEFS object for which we are trying to locate an inode.
5db11c21 768 */
95f5f88f
MM
769struct inode *orangefs_iget(struct super_block *sb,
770 struct orangefs_object_kref *ref)
5db11c21
MM
771{
772 struct inode *inode = NULL;
773 unsigned long hash;
774 int error;
775
8bb8aefd 776 hash = orangefs_handle_hash(ref);
95f5f88f
MM
777 inode = iget5_locked(sb,
778 hash,
779 orangefs_test_inode,
780 orangefs_set_inode,
781 ref);
b5d72cdc
MM
782
783 if (!inode)
784 return ERR_PTR(-ENOMEM);
785
786 if (!(inode->i_state & I_NEW))
5db11c21
MM
787 return inode;
788
8b60785c 789 error = orangefs_inode_getattr(inode, ORANGEFS_GETATTR_NEW);
5db11c21
MM
790 if (error) {
791 iget_failed(inode);
792 return ERR_PTR(error);
793 }
794
795 inode->i_ino = hash; /* needed for stat etc */
8bb8aefd 796 orangefs_init_iops(inode);
5db11c21
MM
797 unlock_new_inode(inode);
798
799 gossip_debug(GOSSIP_INODE_DEBUG,
800 "iget handle %pU, fsid %d hash %ld i_ino %lu\n",
801 &ref->khandle,
802 ref->fs_id,
803 hash,
804 inode->i_ino);
805
806 return inode;
807}
808
809/*
810 * Allocate an inode for a newly created file and insert it into the inode hash.
811 */
8bb8aefd
YL
812struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
813 int mode, dev_t dev, struct orangefs_object_kref *ref)
5db11c21 814{
8bb8aefd 815 unsigned long hash = orangefs_handle_hash(ref);
5db11c21
MM
816 struct inode *inode;
817 int error;
818
819 gossip_debug(GOSSIP_INODE_DEBUG,
5253487e
MM
820 "%s:(sb is %p | MAJOR(dev)=%u | MINOR(dev)=%u mode=%o)\n",
821 __func__,
5db11c21
MM
822 sb,
823 MAJOR(dev),
824 MINOR(dev),
825 mode);
826
827 inode = new_inode(sb);
828 if (!inode)
56249998 829 return ERR_PTR(-ENOMEM);
5db11c21 830
8bb8aefd 831 orangefs_set_inode(inode, ref);
5db11c21
MM
832 inode->i_ino = hash; /* needed for stat etc */
833
8b60785c 834 error = orangefs_inode_getattr(inode, ORANGEFS_GETATTR_NEW);
5db11c21
MM
835 if (error)
836 goto out_iput;
837
8bb8aefd 838 orangefs_init_iops(inode);
5db11c21
MM
839 inode->i_rdev = dev;
840
8bb8aefd 841 error = insert_inode_locked4(inode, hash, orangefs_test_inode, ref);
5db11c21
MM
842 if (error < 0)
843 goto out_iput;
844
845 gossip_debug(GOSSIP_INODE_DEBUG,
846 "Initializing ACL's for inode %pU\n",
847 get_khandle_from_ino(inode));
8bb8aefd 848 orangefs_init_acl(inode, dir);
5db11c21
MM
849 return inode;
850
851out_iput:
852 iput(inode);
853 return ERR_PTR(error);
854}