History

Merge tag 'ceph-for-5.4-rc1' of git://github.com/ceph/ceph-client

Pull ceph updates from Ilya Dryomov: "The highlights are: - automatic recovery of a blacklisted filesystem session (Zheng Yan). This is disabled by default and can be enabled by mounting with the new "recover_session=clean" option. - serialize buffered reads and O_DIRECT writes (Jeff Layton). Care is taken to avoid serializing O_DIRECT reads and writes with each other, this is based on the exclusion scheme from NFS. - handle large osdmaps better in the face of fragmented memory (myself) - don't limit what security.* xattrs can be get or set (Jeff Layton). We were overly restrictive here, unnecessarily preventing things like file capability sets stored in security.capability from working. - allow copy_file_range() within the same inode and across different filesystems within the same cluster (Luis Henriques)" * tag 'ceph-for-5.4-rc1' of git://github.com/ceph/ceph-client: (41 commits) ceph: call ceph_mdsc_destroy from destroy_fs_client libceph: use ceph_kvmalloc() for osdmap arrays libceph: avoid a __vmalloc() deadlock in ceph_kvmalloc() ceph: allow object copies across different filesystems in the same cluster ceph: include ceph_debug.h in cache.c ceph: move static keyword to the front of declarations rbd: pull rbd_img_request_create() dout out into the callers ceph: reconnect connection if session hang in opening state libceph: drop unused con parameter of calc_target() ceph: use release_pages() directly rbd: fix response length parameter for encoded strings ceph: allow arbitrary security.* xattrs ceph: only set CEPH_I_SEC_INITED if we got a MAC label ceph: turn ceph_security_invalidate_secctx into static inline ceph: add buffered/direct exclusionary locking for reads and writes libceph: handle OSD op ceph_pagelist_append() errors ceph: don't return a value from void function ceph: don't freeze during write page faults ceph: update the mtime when truncating up ceph: fix indentation in __get_snap_name() ...

Linus Torvalds committed 7 years ago

Commit f41def32 parents 7b1373d 3ee5a7027 files · +767 −385Browse files

Unified · Split

27 files
  1. Documentation/filesystems/ceph.txt +14 −0
  2. drivers/block/rbd.c +12 −6
  3. fs/ceph/Makefile +1 −1
  4. fs/ceph/addr.c +30 −31
  5. fs/ceph/cache.c +2 −0
  6. fs/ceph/caps.c +88 −85
  7. fs/ceph/debugfs.c +0 −1
  8. fs/ceph/export.c +30 −30
  9. fs/ceph/file.c +64 −40
  10. fs/ceph/inode.c +29 −21
  11. fs/ceph/io.c +163 −0
  12. fs/ceph/io.h +12 −0
  13. fs/ceph/locks.c +6 −2
  14. fs/ceph/mds_client.c +82 −28
  15. fs/ceph/mds_client.h +4 −4
  16. fs/ceph/super.c +47 −5
  17. fs/ceph/super.h +32 −17
  18. fs/ceph/xattr.c +6 −70
  19. include/linux/ceph/libceph.h +1 −0
  20. include/linux/ceph/messenger.h +1 −0
  21. include/linux/ceph/mon_client.h +1 −0
  22. include/linux/ceph/osd_client.h +2 −0
  23. net/ceph/ceph_common.c +31 −6
  24. net/ceph/messenger.c +6 −0
  25. net/ceph/mon_client.c +7 −0
  26. net/ceph/osd_client.c +53 −12
  27. net/ceph/osdmap.c +43 −26
Documentation/filesystems/ceph.txt+14−0
@@ -158,6 +158,20 @@ Mount Options · 157 unmodified lines
158158 copies. Currently, it's only used in copy_file_range, which will revert
159159 to the default VFS implementation if this option is used.
160160
161+ recover_session=<no|clean>
162+ Set auto reconnect mode in the case where the client is blacklisted. The
163+ available modes are "no" and "clean". The default is "no".
164+
165+ * no: never attempt to reconnect when client detects that it has been
166+ blacklisted. Operations will generally fail after being blacklisted.
167+
168+ * clean: client reconnects to the ceph cluster automatically when it
169+ detects that it has been blacklisted. During reconnect, client drops
170+ dirty data/metadata, invalidates page caches and writable file handles.
171+ After reconnect, file locks become stale because the MDS loses track
172+ of them. If an inode contains any stale file locks, read/write on the
173+ inode is not allowed until applications release all stale file locks.
174+
161175 More Information
162176 ================
163177
drivers/block/rbd.c+12−6
@@ -1754,8 +1754,6 @@ static struct rbd_img_request *rbd_img_request_create( · 1753 unmodified lines
17541754 mutex_init(&img_request->state_mutex);
17551755 kref_init(&img_request->kref);
17561756
1757− dout("%s: rbd_dev %p %s -> img %p\n", __func__, rbd_dev,
1758− obj_op_name(op_type), img_request);
17591757 return img_request;
17601758 }
17611759
@@ -2944,6 +2942,9 @@ static int rbd_obj_read_from_parent(struct rbd_obj_request *obj_req) · 1182 unmodified lines
29442942 __set_bit(IMG_REQ_CHILD, &child_img_req->flags);
29452943 child_img_req->obj_request = obj_req;
29462944
2945+ dout("%s child_img_req %p for obj_req %p\n", __func__, child_img_req,
2946+ obj_req);
2947+
29472948 if (!rbd_img_is_write(img_req)) {
29482949 switch (img_req->data_type) {
29492950 case OBJ_REQUEST_BIO:
@@ -4877,6 +4878,9 @@ static void rbd_queue_workfn(struct work_struct *work) · 1927 unmodified lines
48774878 img_request->rq = rq;
48784879 snapc = NULL; /* img_request consumes a ref */
48794880
4881+ dout("%s rbd_dev %p img_req %p %s %llu~%llu\n", __func__, rbd_dev,
4882+ img_request, obj_op_name(op_type), offset, length);
4883+
48804884 if (op_type == OBJ_OP_DISCARD || op_type == OBJ_OP_ZEROOUT)
48814885 result = rbd_img_fill_nodata(img_request, offset, length);
48824886 else
@@ -5669,17 +5673,20 @@ static int rbd_dev_v2_image_size(struct rbd_device *rbd_dev) · 786 unmodified lines
56695673
56705674 static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
56715675 {
5676+ size_t size;
56725677 void *reply_buf;
56735678 int ret;
56745679 void *p;
56755680
5676− reply_buf = kzalloc(RBD_OBJ_PREFIX_LEN_MAX, GFP_KERNEL);
5681+ /* Response will be an encoded string, which includes a length */
5682+ size = sizeof(__le32) + RBD_OBJ_PREFIX_LEN_MAX;
5683+ reply_buf = kzalloc(size, GFP_KERNEL);
56775684 if (!reply_buf)
56785685 return -ENOMEM;
56795686
56805687 ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
56815688 &rbd_dev->header_oloc, "get_object_prefix",
5682− NULL, 0, reply_buf, RBD_OBJ_PREFIX_LEN_MAX);
5689+ NULL, 0, reply_buf, size);
56835690 dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
56845691 if (ret < 0)
56855692 goto out;
@@ -6696,7 +6703,6 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev) · 1010 unmodified lines
66966703 dout("rbd id object name is %s\n", oid.name);
66976704
66986705 /* Response will be an encoded string, which includes a length */
6699−
67006706 size = sizeof (__le32) + RBD_IMAGE_ID_LEN_MAX;
67016707 response = kzalloc(size, GFP_NOIO);
67026708 if (!response) {
@@ -6708,7 +6714,7 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev) · 5 unmodified lines
67086714
67096715 ret = rbd_obj_method_sync(rbd_dev, &oid, &rbd_dev->header_oloc,
67106716 "get_id", NULL, 0,
6711− response, RBD_IMAGE_ID_LEN_MAX);
6717+ response, size);
67126718 dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
67136719 if (ret == -ENOENT) {
67146720 image_id = kstrdup("", GFP_KERNEL);
fs/ceph/Makefile+1−1
@@ -6,7 +6,7 @@ · 5 unmodified lines
66 obj-$(CONFIG_CEPH_FS) += ceph.o
77
88 ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
9− export.o caps.o snap.o xattr.o quota.o \
9+ export.o caps.o snap.o xattr.o quota.o io.o \
1010 mds_client.o mdsmap.o strings.o ceph_frag.o \
1111 debugfs.o
1212
fs/ceph/addr.c+30−31
@@ -189,8 +189,7 @@ static int ceph_do_readpage(struct file *filp, struct page *page) · 188 unmodified lines
189189 {
190190 struct inode *inode = file_inode(filp);
191191 struct ceph_inode_info *ci = ceph_inode(inode);
192− struct ceph_osd_client *osdc =
193− &ceph_inode_to_client(inode)->client->osdc;
192+ struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
194193 int err = 0;
195194 u64 off = page_offset(page);
196195 u64 len = PAGE_SIZE;
@@ -219,8 +218,8 @@ static int ceph_do_readpage(struct file *filp, struct page *page) · 22 unmodified lines
219218
220219 dout("readpage inode %p file %p page %p index %lu\n",
221220 inode, filp, page, page->index);
222− err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout,
223− off, &len,
221+ err = ceph_osdc_readpages(&fsc->client->osdc, ceph_vino(inode),
222+ &ci->i_layout, off, &len,
224223 ci->i_truncate_seq, ci->i_truncate_size,
225224 &page, 1, 0);
226225 if (err == -ENOENT)
@@ -228,6 +227,8 @@ static int ceph_do_readpage(struct file *filp, struct page *page) · 1 unmodified line
228227 if (err < 0) {
229228 SetPageError(page);
230229 ceph_fscache_readpage_cancel(inode, page);
230+ if (err == -EBLACKLISTED)
231+ fsc->blacklisted = true;
231232 goto out;
232233 }
233234 if (err < PAGE_SIZE)
@@ -266,6 +267,8 @@ static void finish_read(struct ceph_osd_request *req) · 32 unmodified lines
266267 int i;
267268
268269 dout("finish_read %p req %p rc %d bytes %d\n", inode, req, rc, bytes);
270+ if (rc == -EBLACKLISTED)
271+ ceph_inode_to_client(inode)->blacklisted = true;
269272
270273 /* unlock all pages, zeroing any data we didn't read */
271274 osd_data = osd_req_op_extent_osd_data(req, 0);
@@ -323,7 +326,8 @@ static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx, · 51 unmodified lines
323326 /* caller of readpages does not hold buffer and read caps
324327 * (fadvise, madvise and readahead cases) */
325328 int want = CEPH_CAP_FILE_CACHE;
326− ret = ceph_try_get_caps(ci, CEPH_CAP_FILE_RD, want, true, &got);
329+ ret = ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want,
330+ true, &got);
327331 if (ret < 0) {
328332 dout("start_read %p, error getting cap\n", inode);
329333 } else if (!(got & want)) {
@@ -569,7 +573,7 @@ static u64 get_writepages_data_length(struct inode *inode, · 239 unmodified lines
569573 /*
570574 * Write a single page, but leave the page locked.
571575 *
572− * If we get a write error, set the page error bit, but still adjust the
576+ * If we get a write error, mark the mapping for error, but still adjust the
573577 * dirty page accounting (i.e., page is no longer dirty).
574578 */
575579 static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
@@ -640,9 +644,10 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) · 64 unmodified lines
640644 end_page_writeback(page);
641645 return err;
642646 }
647+ if (err == -EBLACKLISTED)
648+ fsc->blacklisted = true;
643649 dout("writepage setting page/mapping error %d %p\n",
644650 err, page);
645− SetPageError(page);
646651 mapping_set_error(&inode->i_data, err);
647652 wbc->pages_skipped++;
648653 } else {
@@ -679,23 +684,6 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc) · 30 unmodified lines
679684 return err;
680685 }
681686
682−/*
683− * lame release_pages helper. release_pages() isn't exported to
684− * modules.
685− */
686−static void ceph_release_pages(struct page **pages, int num)
687−{
688− struct pagevec pvec;
689− int i;
690−
691− pagevec_init(&pvec);
692− for (i = 0; i < num; i++) {
693− if (pagevec_add(&pvec, pages[i]) == 0)
694− pagevec_release(&pvec);
695− }
696− pagevec_release(&pvec);
697−}
698−
699687 /*
700688 * async writeback completion handler.
701689 *
@@ -720,6 +708,8 @@ static void writepages_finish(struct ceph_osd_request *req) · 18 unmodified lines
720708 if (rc < 0) {
721709 mapping_set_error(mapping, rc);
722710 ceph_set_error_write(ci);
711+ if (rc == -EBLACKLISTED)
712+ fsc->blacklisted = true;
723713 } else {
724714 ceph_clear_error_write(ci);
725715 }
@@ -769,7 +759,7 @@ static void writepages_finish(struct ceph_osd_request *req) · 43 unmodified lines
769759 dout("writepages_finish %p wrote %llu bytes cleaned %d pages\n",
770760 inode, osd_data->length, rc >= 0 ? num_pages : 0);
771761
772− ceph_release_pages(osd_data->pages, num_pages);
762+ release_pages(osd_data->pages, num_pages);
773763 }
774764
775765 ceph_put_wrbuffer_cap_refs(ci, total_pages, snapc);
@@ -1452,7 +1442,8 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf) · 676 unmodified lines
14521442 want = CEPH_CAP_FILE_CACHE;
14531443
14541444 got = 0;
1455− err = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, -1, &got, &pinned_page);
1445+ err = ceph_get_caps(vma->vm_file, CEPH_CAP_FILE_RD, want, -1,
1446+ &got, &pinned_page);
14561447 if (err < 0)
14571448 goto out_restore;
14581449
@@ -1540,6 +1531,7 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf) · 81 unmodified lines
15401531 if (!prealloc_cf)
15411532 return VM_FAULT_OOM;
15421533
1534+ sb_start_pagefault(inode->i_sb);
15431535 ceph_block_sigs(&oldset);
15441536
15451537 if (ci->i_inline_version != CEPH_INLINE_NONE) {
@@ -1568,7 +1560,7 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf) · 22 unmodified lines
15681560 want = CEPH_CAP_FILE_BUFFER;
15691561
15701562 got = 0;
1571− err = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, off + len,
1563+ err = ceph_get_caps(vma->vm_file, CEPH_CAP_FILE_WR, want, off + len,
15721564 &got, NULL);
15731565 if (err < 0)
15741566 goto out_free;
@@ -1614,6 +1606,7 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf) · 39 unmodified lines
16141606 ceph_put_cap_refs(ci, got);
16151607 out_free:
16161608 ceph_restore_sigs(&oldset);
1609+ sb_end_pagefault(inode->i_sb);
16171610 ceph_free_cap_flush(prealloc_cf);
16181611 if (err < 0)
16191612 ret = vmf_error(err);
@@ -1946,12 +1939,17 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, · 326 unmodified lines
19461939
19471940 if (err >= 0 || err == -ENOENT)
19481941 have |= POOL_READ;
1949− else if (err != -EPERM)
1942+ else if (err != -EPERM) {
1943+ if (err == -EBLACKLISTED)
1944+ fsc->blacklisted = true;
19501945 goto out_unlock;
1946+ }
19511947
19521948 if (err2 == 0 || err2 == -EEXIST)
19531949 have |= POOL_WRITE;
19541950 else if (err2 != -EPERM) {
1951+ if (err2 == -EBLACKLISTED)
1952+ fsc->blacklisted = true;
19551953 err = err2;
19561954 goto out_unlock;
19571955 }
@@ -1989,10 +1987,11 @@ out: · 31 unmodified lines
19891987 return err;
19901988 }
19911989
1992−int ceph_pool_perm_check(struct ceph_inode_info *ci, int need)
1990+int ceph_pool_perm_check(struct inode *inode, int need)
19931991 {
1994− s64 pool;
1992+ struct ceph_inode_info *ci = ceph_inode(inode);
19951993 struct ceph_string *pool_ns;
1994+ s64 pool;
19961995 int ret, flags;
19971996
19981997 if (ci->i_vino.snap != CEPH_NOSNAP) {
@@ -2004,7 +2003,7 @@ int ceph_pool_perm_check(struct ceph_inode_info *ci, int need) · 5 unmodified lines
20042003 return 0;
20052004 }
20062005
2007− if (ceph_test_mount_opt(ceph_inode_to_client(&ci->vfs_inode),
2006+ if (ceph_test_mount_opt(ceph_inode_to_client(inode),
20082007 NOPOOLPERM))
20092008 return 0;
20102009
fs/ceph/cache.c+2−0
@@ -6,6 +6,8 @@ · 5 unmodified lines
66 * Written by Milosz Tanski (milosz@adfin.com)
77 */
88
9+#include <linux/ceph/ceph_debug.h>
10+
911 #include "super.h"
1012 #include "cache.h"
1113
fs/ceph/caps.c+88−85
@@ -457,37 +457,6 @@ struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci, int mds) · 456 unmodified lines
457457 return cap;
458458 }
459459
460−/*
461− * Return id of any MDS with a cap, preferably FILE_WR|BUFFER|EXCL, else -1.
462− */
463−static int __ceph_get_cap_mds(struct ceph_inode_info *ci)
464−{
465− struct ceph_cap *cap;
466− int mds = -1;
467− struct rb_node *p;
468−
469− /* prefer mds with WR|BUFFER|EXCL caps */
470− for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
471− cap = rb_entry(p, struct ceph_cap, ci_node);
472− mds = cap->mds;
473− if (cap->issued & (CEPH_CAP_FILE_WR |
474− CEPH_CAP_FILE_BUFFER |
475− CEPH_CAP_FILE_EXCL))
476− break;
477− }
478− return mds;
479−}
480−
481−int ceph_get_cap_mds(struct inode *inode)
482−{
483− struct ceph_inode_info *ci = ceph_inode(inode);
484− int mds;
485− spin_lock(&ci->i_ceph_lock);
486− mds = __ceph_get_cap_mds(ceph_inode(inode));
487− spin_unlock(&ci->i_ceph_lock);
488− return mds;
489−}
490−
491460 /*
492461 * Called under i_ceph_lock.
493462 */
@@ -628,7 +597,7 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap, · 134 unmodified lines
628597 /*
629598 * Add a capability under the given MDS session.
630599 *
631− * Caller should hold session snap_rwsem (read) and s_mutex.
600+ * Caller should hold session snap_rwsem (read) and ci->i_ceph_lock
632601 *
633602 * @fmode is the open file mode, if we are opening a file, otherwise
634603 * it is < 0. (This is so we can atomically add the cap and add an
@@ -645,6 +614,9 @@ void ceph_add_cap(struct inode *inode, · 10 unmodified lines
645614 struct ceph_cap *cap;
646615 int mds = session->s_mds;
647616 int actual_wanted;
617+ u32 gen;
618+
619+ lockdep_assert_held(&ci->i_ceph_lock);
648620
649621 dout("add_cap %p mds%d cap %llx %s seq %d\n", inode,
650622 session->s_mds, cap_id, ceph_cap_string(issued), seq);
@@ -656,6 +628,10 @@ void ceph_add_cap(struct inode *inode, · 5 unmodified lines
656628 if (fmode >= 0)
657629 wanted |= ceph_caps_for_mode(fmode);
658630
631+ spin_lock(&session->s_gen_ttl_lock);
632+ gen = session->s_cap_gen;
633+ spin_unlock(&session->s_gen_ttl_lock);
634+
659635 cap = __get_cap_for_mds(ci, mds);
660636 if (!cap) {
661637 cap = *new_cap;
@@ -681,7 +657,7 @@ void ceph_add_cap(struct inode *inode, · 19 unmodified lines
681657 list_move_tail(&cap->session_caps, &session->s_caps);
682658 spin_unlock(&session->s_cap_lock);
683659
684− if (cap->cap_gen < session->s_cap_gen)
660+ if (cap->cap_gen < gen)
685661 cap->issued = cap->implemented = CEPH_CAP_PIN;
686662
687663 /*
@@ -775,7 +751,7 @@ void ceph_add_cap(struct inode *inode, · 87 unmodified lines
775751 cap->seq = seq;
776752 cap->issue_seq = seq;
777753 cap->mseq = mseq;
778− cap->cap_gen = session->s_cap_gen;
754+ cap->cap_gen = gen;
779755
780756 if (fmode >= 0)
781757 __ceph_get_fmode(ci, fmode);
@@ -1284,10 +1260,6 @@ void __ceph_remove_caps(struct ceph_inode_info *ci) · 502 unmodified lines
12841260 * Make note of max_size reported/requested from mds, revoked caps
12851261 * that have now been implemented.
12861262 *
1287− * Make half-hearted attempt ot to invalidate page cache if we are
1288− * dropping RDCACHE. Note that this will leave behind locked pages
1289− * that we'll then need to deal with elsewhere.
1290− *
12911263 * Return non-zero if delayed release, or we experienced an error
12921264 * such that the caller should requeue + retry later.
12931265 *
@@ -1746,11 +1718,11 @@ static bool __finish_cap_flush(struct ceph_mds_client *mdsc, · 452 unmodified lines
17461718 * Add dirty inode to the flushing list. Assigned a seq number so we
17471719 * can wait for caps to flush without starving.
17481720 *
1749− * Called under i_ceph_lock.
1721+ * Called under i_ceph_lock. Returns the flush tid.
17501722 */
1751−static int __mark_caps_flushing(struct inode *inode,
1723+static u64 __mark_caps_flushing(struct inode *inode,
17521724 struct ceph_mds_session *session, bool wake,
1753− u64 *flush_tid, u64 *oldest_flush_tid)
1725+ u64 *oldest_flush_tid)
17541726 {
17551727 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
17561728 struct ceph_inode_info *ci = ceph_inode(inode);
@@ -1789,8 +1761,7 @@ static int __mark_caps_flushing(struct inode *inode, · 32 unmodified lines
17891761
17901762 list_add_tail(&cf->i_list, &ci->i_cap_flush_list);
17911763
1792− *flush_tid = cf->tid;
1793− return flushing;
1764+ return cf->tid;
17941765 }
17951766
17961767 /*
@@ -2028,11 +1999,6 @@ retry_locked: · 231 unmodified lines
20281999 }
20292000
20302001 ack:
2031− if (ci->i_ceph_flags & CEPH_I_NOFLUSH) {
2032− dout(" skipping %p I_NOFLUSH set\n", inode);
2033− continue;
2034− }
2035−
20362002 if (session && session != cap->session) {
20372003 dout("oops, wrong session %p mutex\n", session);
20382004 mutex_unlock(&session->s_mutex);
@@ -2080,9 +2046,9 @@ ack: · 41 unmodified lines
20802046 }
20812047
20822048 if (cap == ci->i_auth_cap && ci->i_dirty_caps) {
2083− flushing = __mark_caps_flushing(inode, session, false,
2084− &flush_tid,
2085− &oldest_flush_tid);
2049+ flushing = ci->i_dirty_caps;
2050+ flush_tid = __mark_caps_flushing(inode, session, false,
2051+ &oldest_flush_tid);
20862052 } else {
20872053 flushing = 0;
20882054 flush_tid = 0;
@@ -2130,16 +2096,11 @@ static int try_flush_caps(struct inode *inode, u64 *ptid) · 41 unmodified lines
21302096 retry:
21312097 spin_lock(&ci->i_ceph_lock);
21322098 retry_locked:
2133− if (ci->i_ceph_flags & CEPH_I_NOFLUSH) {
2134− spin_unlock(&ci->i_ceph_lock);
2135− dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode);
2136− goto out;
2137− }
21382099 if (ci->i_dirty_caps && ci->i_auth_cap) {
21392100 struct ceph_cap *cap = ci->i_auth_cap;
21402101 int delayed;
21412102
2142− if (!session || session != cap->session) {
2103+ if (session != cap->session) {
21432104 spin_unlock(&ci->i_ceph_lock);
21442105 if (session)
21452106 mutex_unlock(&session->s_mutex);
@@ -2161,8 +2122,9 @@ retry_locked: · 15 unmodified lines
21612122 goto retry_locked;
21622123 }
21632124
2164− flushing = __mark_caps_flushing(inode, session, true,
2165− &flush_tid, &oldest_flush_tid);
2125+ flushing = ci->i_dirty_caps;
2126+ flush_tid = __mark_caps_flushing(inode, session, true,
2127+ &oldest_flush_tid);
21662128
21672129 /* __send_cap drops i_ceph_lock */
21682130 delayed = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH,
@@ -2261,35 +2223,45 @@ static int unsafe_request_wait(struct inode *inode) · 92 unmodified lines
22612223
22622224 int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
22632225 {
2226+ struct ceph_file_info *fi = file->private_data;
22642227 struct inode *inode = file->f_mapping->host;
22652228 struct ceph_inode_info *ci = ceph_inode(inode);
22662229 u64 flush_tid;
2267− int ret;
2230+ int ret, err;
22682231 int dirty;
22692232
22702233 dout("fsync %p%s\n", inode, datasync ? " datasync" : "");
22712234
22722235 ret = file_write_and_wait_range(file, start, end);
2273− if (ret < 0)
2274− goto out;
2275−
22762236 if (datasync)
22772237 goto out;
22782238
22792239 dirty = try_flush_caps(inode, &flush_tid);
22802240 dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
22812241
2282− ret = unsafe_request_wait(inode);
2242+ err = unsafe_request_wait(inode);
22832243
22842244 /*
22852245 * only wait on non-file metadata writeback (the mds
22862246 * can recover size and mtime, so we don't need to
22872247 * wait for that)
22882248 */
2289− if (!ret && (dirty & ~CEPH_CAP_ANY_FILE_WR)) {
2290− ret = wait_event_interruptible(ci->i_cap_wq,
2249+ if (!err && (dirty & ~CEPH_CAP_ANY_FILE_WR)) {
2250+ err = wait_event_interruptible(ci->i_cap_wq,
22912251 caps_are_flushed(inode, flush_tid));
22922252 }
2253+
2254+ if (err < 0)
2255+ ret = err;
2256+
2257+ if (errseq_check(&ci->i_meta_err, READ_ONCE(fi->meta_err))) {
2258+ spin_lock(&file->f_lock);
2259+ err = errseq_check_and_advance(&ci->i_meta_err,
2260+ &fi->meta_err);
2261+ spin_unlock(&file->f_lock);
2262+ if (err < 0)
2263+ ret = err;
2264+ }
22932265 out:
22942266 dout("fsync %p%s result=%d\n", inode, datasync ? " datasync" : "", ret);
22952267 return ret;
@@ -2560,10 +2532,15 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got, · 264 unmodified lines
25602532 *
25612533 * FIXME: how does a 0 return differ from -EAGAIN?
25622534 */
2563−static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want,
2564− loff_t endoff, bool nonblock, int *got)
2535+enum {
2536+ NON_BLOCKING = 1,
2537+ CHECK_FILELOCK = 2,
2538+};
2539+
2540+static int try_get_cap_refs(struct inode *inode, int need, int want,
2541+ loff_t endoff, int flags, int *got)
25652542 {
2566− struct inode *inode = &ci->vfs_inode;
2543+ struct ceph_inode_info *ci = ceph_inode(inode);
25672544 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
25682545 int ret = 0;
25692546 int have, implemented;
@@ -2576,6 +2553,13 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want, · 6 unmodified lines
25762553 again:
25772554 spin_lock(&ci->i_ceph_lock);
25782555
2556+ if ((flags & CHECK_FILELOCK) &&
2557+ (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK)) {
2558+ dout("try_get_cap_refs %p error filelock\n", inode);
2559+ ret = -EIO;
2560+ goto out_unlock;
2561+ }
2562+
25792563 /* make sure file is actually open */
25802564 file_wanted = __ceph_caps_file_wanted(ci);
25812565 if ((file_wanted & need) != need) {
@@ -2637,7 +2621,7 @@ again: · 55 unmodified lines
26372621 * we can not call down_read() when
26382622 * task isn't in TASK_RUNNING state
26392623 */
2640− if (nonblock) {
2624+ if (flags & NON_BLOCKING) {
26412625 ret = -EAGAIN;
26422626 goto out_unlock;
26432627 }
@@ -2731,18 +2715,19 @@ static void check_max_size(struct inode *inode, loff_t endoff) · 87 unmodified lines
27312715 ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
27322716 }
27332717
2734−int ceph_try_get_caps(struct ceph_inode_info *ci, int need, int want,
2718+int ceph_try_get_caps(struct inode *inode, int need, int want,
27352719 bool nonblock, int *got)
27362720 {
27372721 int ret;
27382722
27392723 BUG_ON(need & ~CEPH_CAP_FILE_RD);
27402724 BUG_ON(want & ~(CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO|CEPH_CAP_FILE_SHARED));
2741− ret = ceph_pool_perm_check(ci, need);
2725+ ret = ceph_pool_perm_check(inode, need);
27422726 if (ret < 0)
27432727 return ret;
27442728
2745− ret = try_get_cap_refs(ci, need, want, 0, nonblock, got);
2729+ ret = try_get_cap_refs(inode, need, want, 0,
2730+ (nonblock ? NON_BLOCKING : 0), got);
27462731 return ret == -EAGAIN ? 0 : ret;
27472732 }
27482733
@@ -2751,30 +2736,40 @@ int ceph_try_get_caps(struct ceph_inode_info *ci, int need, int want, · 2 unmodified lines
27512736 * due to a small max_size, make sure we check_max_size (and possibly
27522737 * ask the mds) so we don't get hung up indefinitely.
27532738 */
2754−int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
2739+int ceph_get_caps(struct file *filp, int need, int want,
27552740 loff_t endoff, int *got, struct page **pinned_page)
27562741 {
2757− int _got, ret;
2742+ struct ceph_file_info *fi = filp->private_data;
2743+ struct inode *inode = file_inode(filp);
2744+ struct ceph_inode_info *ci = ceph_inode(inode);
2745+ struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
2746+ int ret, _got, flags;
27582747
2759− ret = ceph_pool_perm_check(ci, need);
2748+ ret = ceph_pool_perm_check(inode, need);
27602749 if (ret < 0)
27612750 return ret;
27622751
2752+ if ((fi->fmode & CEPH_FILE_MODE_WR) &&
2753+ fi->filp_gen != READ_ONCE(fsc->filp_gen))
2754+ return -EBADF;
2755+
27632756 while (true) {
27642757 if (endoff > 0)
2765− check_max_size(&ci->vfs_inode, endoff);
2758+ check_max_size(inode, endoff);
27662759
2760+ flags = atomic_read(&fi->num_locks) ? CHECK_FILELOCK : 0;
27672761 _got = 0;
2768− ret = try_get_cap_refs(ci, need, want, endoff,
2769− false, &_got);
2762+ ret = try_get_cap_refs(inode, need, want, endoff,
2763+ flags, &_got);
27702764 if (ret == -EAGAIN)
27712765 continue;
27722766 if (!ret) {
27732767 DEFINE_WAIT_FUNC(wait, woken_wake_function);
27742768 add_wait_queue(&ci->i_cap_wq, &wait);
27752769
2776− while (!(ret = try_get_cap_refs(ci, need, want, endoff,
2777− true, &_got))) {
2770+ flags |= NON_BLOCKING;
2771+ while (!(ret = try_get_cap_refs(inode, need, want,
2772+ endoff, flags, &_got))) {
27782773 if (signal_pending(current)) {
27792774 ret = -ERESTARTSYS;
27802775 break;
@@ -2786,10 +2781,18 @@ int ceph_get_caps(struct ceph_inode_info *ci, int need, int want, · 5 unmodified lines
27862781 if (ret == -EAGAIN)
27872782 continue;
27882783 }
2784+
2785+ if ((fi->fmode & CEPH_FILE_MODE_WR) &&
2786+ fi->filp_gen != READ_ONCE(fsc->filp_gen)) {
2787+ if (ret >= 0 && _got)
2788+ ceph_put_cap_refs(ci, _got);
2789+ return -EBADF;
2790+ }
2791+
27892792 if (ret < 0) {
27902793 if (ret == -ESTALE) {
27912794 /* session was killed, try renew caps */
2792− ret = ceph_renew_caps(&ci->vfs_inode);
2795+ ret = ceph_renew_caps(inode);
27932796 if (ret == 0)
27942797 continue;
27952798 }
@@ -2798,9 +2801,9 @@ int ceph_get_caps(struct ceph_inode_info *ci, int need, int want, · 2 unmodified lines
27982801
27992802 if (ci->i_inline_version != CEPH_INLINE_NONE &&
28002803 (_got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) &&
2801− i_size_read(&ci->vfs_inode) > 0) {
2804+ i_size_read(inode) > 0) {
28022805 struct page *page =
2803− find_get_page(ci->vfs_inode.i_mapping, 0);
2806+ find_get_page(inode->i_mapping, 0);
28042807 if (page) {
28052808 if (PageUptodate(page)) {
28062809 *pinned_page = page;
@@ -2819,7 +2822,7 @@ int ceph_get_caps(struct ceph_inode_info *ci, int need, int want, · 12 unmodified lines
28192822 * getattr request will bring inline data into
28202823 * page cache
28212824 */
2822− ret = __ceph_do_getattr(&ci->vfs_inode, NULL,
2825+ ret = __ceph_do_getattr(inode, NULL,
28232826 CEPH_STAT_CAP_INLINE_DATA,
28242827 true);
28252828 if (ret < 0)
fs/ceph/debugfs.c+0−1
@@ -294,7 +294,6 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc) · 293 unmodified lines
294294
295295 void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
296296 {
297− return 0;
298297 }
299298
300299 void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
fs/ceph/export.c+30−30
@@ -35,7 +35,7 @@ struct ceph_nfs_snapfh { · 34 unmodified lines
3535 static int ceph_encode_snapfh(struct inode *inode, u32 *rawfh, int *max_len,
3636 struct inode *parent_inode)
3737 {
38− const static int snap_handle_length =
38+ static const int snap_handle_length =
3939 sizeof(struct ceph_nfs_snapfh) >> 2;
4040 struct ceph_nfs_snapfh *sfh = (void *)rawfh;
4141 u64 snapid = ceph_snap(inode);
@@ -85,9 +85,9 @@ out: · 43 unmodified lines
8585 static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
8686 struct inode *parent_inode)
8787 {
88− const static int handle_length =
88+ static const int handle_length =
8989 sizeof(struct ceph_nfs_fh) >> 2;
90− const static int connected_handle_length =
90+ static const int connected_handle_length =
9191 sizeof(struct ceph_nfs_confh) >> 2;
9292 int type;
9393
@@ -458,33 +458,33 @@ static int __get_snap_name(struct dentry *parent, char *name, · 364 unmodified lines
458458 if (err < 0)
459459 goto out;
460460
461− rinfo = &req->r_reply_info;
462− for (i = 0; i < rinfo->dir_nr; i++) {
463− rde = rinfo->dir_entries + i;
464− BUG_ON(!rde->inode.in);
465− if (ceph_snap(inode) ==
466− le64_to_cpu(rde->inode.in->snapid)) {
467− memcpy(name, rde->name, rde->name_len);
468− name[rde->name_len] = '\0';
469− err = 0;
470− goto out;
471− }
472− }
473−
474− if (rinfo->dir_end)
475− break;
476−
477− BUG_ON(rinfo->dir_nr <= 0);
478− rde = rinfo->dir_entries + (rinfo->dir_nr - 1);
479− next_offset += rinfo->dir_nr;
480− last_name = kstrndup(rde->name, rde->name_len, GFP_KERNEL);
481− if (!last_name) {
482− err = -ENOMEM;
483− goto out;
484− }
485−
486− ceph_mdsc_put_request(req);
487− req = NULL;
461+ rinfo = &req->r_reply_info;
462+ for (i = 0; i < rinfo->dir_nr; i++) {
463+ rde = rinfo->dir_entries + i;
464+ BUG_ON(!rde->inode.in);
465+ if (ceph_snap(inode) ==
466+ le64_to_cpu(rde->inode.in->snapid)) {
467+ memcpy(name, rde->name, rde->name_len);
468+ name[rde->name_len] = '\0';
469+ err = 0;
470+ goto out;
471+ }
472+ }
473+
474+ if (rinfo->dir_end)
475+ break;
476+
477+ BUG_ON(rinfo->dir_nr <= 0);
478+ rde = rinfo->dir_entries + (rinfo->dir_nr - 1);
479+ next_offset += rinfo->dir_nr;
480+ last_name = kstrndup(rde->name, rde->name_len, GFP_KERNEL);
481+ if (!last_name) {
482+ err = -ENOMEM;
483+ goto out;
484+ }
485+
486+ ceph_mdsc_put_request(req);
487+ req = NULL;
488488 }
489489 err = -ENOENT;
490490 out:
fs/ceph/file.c+64−40
@@ -15,6 +15,7 @@ · 14 unmodified lines
1515 #include "super.h"
1616 #include "mds_client.h"
1717 #include "cache.h"
18+#include "io.h"
1819
1920 static __le32 ceph_flags_sys2wire(u32 flags)
2021 {
@@ -201,6 +202,7 @@ out: · 180 unmodified lines
201202 static int ceph_init_file_info(struct inode *inode, struct file *file,
202203 int fmode, bool isdir)
203204 {
205+ struct ceph_inode_info *ci = ceph_inode(inode);
204206 struct ceph_file_info *fi;
205207
206208 dout("%s %p %p 0%o (%s)\n", __func__, inode, file,
@@ -211,7 +213,7 @@ static int ceph_init_file_info(struct inode *inode, struct file *file, · 4 unmodified lines
211213 struct ceph_dir_file_info *dfi =
212214 kmem_cache_zalloc(ceph_dir_file_cachep, GFP_KERNEL);
213215 if (!dfi) {
214− ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */
216+ ceph_put_fmode(ci, fmode); /* clean up */
215217 return -ENOMEM;
216218 }
217219
@@ -222,7 +224,7 @@ static int ceph_init_file_info(struct inode *inode, struct file *file, · 4 unmodified lines
222224 } else {
223225 fi = kmem_cache_zalloc(ceph_file_cachep, GFP_KERNEL);
224226 if (!fi) {
225− ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */
227+ ceph_put_fmode(ci, fmode); /* clean up */
226228 return -ENOMEM;
227229 }
228230
@@ -232,6 +234,8 @@ static int ceph_init_file_info(struct inode *inode, struct file *file, · 3 unmodified lines
232234 fi->fmode = fmode;
233235 spin_lock_init(&fi->rw_contexts_lock);
234236 INIT_LIST_HEAD(&fi->rw_contexts);
237+ fi->meta_err = errseq_sample(&ci->i_meta_err);
238+ fi->filp_gen = READ_ONCE(ceph_inode_to_client(inode)->filp_gen);
235239
236240 return 0;
237241 }
@@ -695,7 +699,13 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to, · 457 unmodified lines
695699 ceph_release_page_vector(pages, num_pages);
696700 }
697701
698− if (ret <= 0 || off >= i_size || !more)
702+ if (ret < 0) {
703+ if (ret == -EBLACKLISTED)
704+ fsc->blacklisted = true;
705+ break;
706+ }
707+
708+ if (off >= i_size || !more)
699709 break;
700710 }
701711
@@ -921,7 +931,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter, · 219 unmodified lines
921931 struct ceph_aio_request *aio_req = NULL;
922932 int num_pages = 0;
923933 int flags;
924− int ret;
934+ int ret = 0;
925935 struct timespec64 mtime = current_time(inode);
926936 size_t count = iov_iter_count(iter);
927937 loff_t pos = iocb->ki_pos;
@@ -935,11 +945,6 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter, · 7 unmodified lines
935945 (write ? "write" : "read"), file, pos, (unsigned)count,
936946 snapc, snapc ? snapc->seq : 0);
937947
938− ret = filemap_write_and_wait_range(inode->i_mapping,
939− pos, pos + count - 1);
940− if (ret < 0)
941− return ret;
942−
943948 if (write) {
944949 int ret2 = invalidate_inode_pages2_range(inode->i_mapping,
945950 pos >> PAGE_SHIFT,
@@ -1260,7 +1265,8 @@ again: · 314 unmodified lines
12601265 want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
12611266 else
12621267 want = CEPH_CAP_FILE_CACHE;
1263− ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, -1, &got, &pinned_page);
1268+ ret = ceph_get_caps(filp, CEPH_CAP_FILE_RD, want, -1,
1269+ &got, &pinned_page);
12641270 if (ret < 0)
12651271 return ret;
12661272
@@ -1274,12 +1280,16 @@ again: · 7 unmodified lines
12741280
12751281 if (ci->i_inline_version == CEPH_INLINE_NONE) {
12761282 if (!retry_op && (iocb->ki_flags & IOCB_DIRECT)) {
1283+ ceph_start_io_direct(inode);
12771284 ret = ceph_direct_read_write(iocb, to,
12781285 NULL, NULL);
1286+ ceph_end_io_direct(inode);
12791287 if (ret >= 0 && ret < len)
12801288 retry_op = CHECK_EOF;
12811289 } else {
1290+ ceph_start_io_read(inode);
12821291 ret = ceph_sync_read(iocb, to, &retry_op);
1292+ ceph_end_io_read(inode);
12831293 }
12841294 } else {
12851295 retry_op = READ_INLINE;
@@ -1290,7 +1300,9 @@ again: · 4 unmodified lines
12901300 inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
12911301 ceph_cap_string(got));
12921302 ceph_add_rw_context(fi, &rw_ctx);
1303+ ceph_start_io_read(inode);
12931304 ret = generic_file_read_iter(iocb, to);
1305+ ceph_end_io_read(inode);
12941306 ceph_del_rw_context(fi, &rw_ctx);
12951307 }
12961308 dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
@@ -1399,7 +1411,10 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) · 102 unmodified lines
13991411 return -ENOMEM;
14001412
14011413 retry_snap:
1402− inode_lock(inode);
1414+ if (iocb->ki_flags & IOCB_DIRECT)
1415+ ceph_start_io_direct(inode);
1416+ else
1417+ ceph_start_io_write(inode);
14031418
14041419 /* We can write back this queue in page reclaim */
14051420 current->backing_dev_info = inode_to_bdi(inode);
@@ -1457,7 +1472,7 @@ retry_snap: · 51 unmodified lines
14571472 else
14581473 want = CEPH_CAP_FILE_BUFFER;
14591474 got = 0;
1460− err = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, pos + count,
1475+ err = ceph_get_caps(file, CEPH_CAP_FILE_WR, want, pos + count,
14611476 &got, NULL);
14621477 if (err < 0)
14631478 goto out;
@@ -1470,7 +1485,6 @@ retry_snap: · 6 unmodified lines
14701485 (ci->i_ceph_flags & CEPH_I_ERROR_WRITE)) {
14711486 struct ceph_snap_context *snapc;
14721487 struct iov_iter data;
1473− inode_unlock(inode);
14741488
14751489 spin_lock(&ci->i_ceph_lock);
14761490 if (__ceph_have_pending_cap_snap(ci)) {
@@ -1487,11 +1501,14 @@ retry_snap: · 10 unmodified lines
14871501
14881502 /* we might need to revert back to that point */
14891503 data = *from;
1490− if (iocb->ki_flags & IOCB_DIRECT)
1504+ if (iocb->ki_flags & IOCB_DIRECT) {
14911505 written = ceph_direct_read_write(iocb, &data, snapc,
14921506 &prealloc_cf);
1493− else
1507+ ceph_end_io_direct(inode);
1508+ } else {
14941509 written = ceph_sync_write(iocb, &data, pos, snapc);
1510+ ceph_end_io_write(inode);
1511+ }
14951512 if (written > 0)
14961513 iov_iter_advance(from, written);
14971514 ceph_put_snap_context(snapc);
@@ -1506,7 +1523,7 @@ retry_snap: · 8 unmodified lines
15061523 written = generic_perform_write(file, from, pos);
15071524 if (likely(written >= 0))
15081525 iocb->ki_pos = pos + written;
1509− inode_unlock(inode);
1526+ ceph_end_io_write(inode);
15101527 }
15111528
15121529 if (written >= 0) {
@@ -1541,9 +1558,11 @@ retry_snap: · 28 unmodified lines
15411558 }
15421559
15431560 goto out_unlocked;
1544−
15451561 out:
1546− inode_unlock(inode);
1562+ if (iocb->ki_flags & IOCB_DIRECT)
1563+ ceph_end_io_direct(inode);
1564+ else
1565+ ceph_end_io_write(inode);
15471566 out_unlocked:
15481567 ceph_free_cap_flush(prealloc_cf);
15491568 current->backing_dev_info = NULL;
@@ -1781,7 +1800,7 @@ static long ceph_fallocate(struct file *file, int mode, · 231 unmodified lines
17811800 else
17821801 want = CEPH_CAP_FILE_BUFFER;
17831802
1784− ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, endoff, &got, NULL);
1803+ ret = ceph_get_caps(file, CEPH_CAP_FILE_WR, want, endoff, &got, NULL);
17851804 if (ret < 0)
17861805 goto unlock;
17871806
@@ -1810,16 +1829,15 @@ unlock: · 22 unmodified lines
18101829 * src_ci. Two attempts are made to obtain both caps, and an error is return if
18111830 * this fails; zero is returned on success.
18121831 */
1813−static int get_rd_wr_caps(struct ceph_inode_info *src_ci,
1814− loff_t src_endoff, int *src_got,
1815− struct ceph_inode_info *dst_ci,
1832+static int get_rd_wr_caps(struct file *src_filp, int *src_got,
1833+ struct file *dst_filp,
18161834 loff_t dst_endoff, int *dst_got)
18171835 {
18181836 int ret = 0;
18191837 bool retrying = false;
18201838
18211839 retry_caps:
1822− ret = ceph_get_caps(dst_ci, CEPH_CAP_FILE_WR, CEPH_CAP_FILE_BUFFER,
1840+ ret = ceph_get_caps(dst_filp, CEPH_CAP_FILE_WR, CEPH_CAP_FILE_BUFFER,
18231841 dst_endoff, dst_got, NULL);
18241842 if (ret < 0)
18251843 return ret;
@@ -1829,24 +1847,24 @@ retry_caps: · 3 unmodified lines
18291847 * we would risk a deadlock by using ceph_get_caps. Thus, we'll do some
18301848 * retry dance instead to try to get both capabilities.
18311849 */
1832− ret = ceph_try_get_caps(src_ci, CEPH_CAP_FILE_RD, CEPH_CAP_FILE_SHARED,
1850+ ret = ceph_try_get_caps(file_inode(src_filp),
1851+ CEPH_CAP_FILE_RD, CEPH_CAP_FILE_SHARED,
18331852 false, src_got);
18341853 if (ret <= 0) {
18351854 /* Start by dropping dst_ci caps and getting src_ci caps */
1836− ceph_put_cap_refs(dst_ci, *dst_got);
1855+ ceph_put_cap_refs(ceph_inode(file_inode(dst_filp)), *dst_got);
18371856 if (retrying) {
18381857 if (!ret)
18391858 /* ceph_try_get_caps masks EAGAIN */
18401859 ret = -EAGAIN;
18411860 return ret;
18421861 }
1843− ret = ceph_get_caps(src_ci, CEPH_CAP_FILE_RD,
1844− CEPH_CAP_FILE_SHARED, src_endoff,
1845− src_got, NULL);
1862+ ret = ceph_get_caps(src_filp, CEPH_CAP_FILE_RD,
1863+ CEPH_CAP_FILE_SHARED, -1, src_got, NULL);
18461864 if (ret < 0)
18471865 return ret;
18481866 /*... drop src_ci caps too, and retry */
1849− ceph_put_cap_refs(src_ci, *src_got);
1867+ ceph_put_cap_refs(ceph_inode(file_inode(src_filp)), *src_got);
18501868 retrying = true;
18511869 goto retry_caps;
18521870 }
@@ -1904,6 +1922,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, · 51 unmodified lines
19041922 struct ceph_inode_info *src_ci = ceph_inode(src_inode);
19051923 struct ceph_inode_info *dst_ci = ceph_inode(dst_inode);
19061924 struct ceph_cap_flush *prealloc_cf;
1925+ struct ceph_fs_client *src_fsc = ceph_inode_to_client(src_inode);
19071926 struct ceph_object_locator src_oloc, dst_oloc;
19081927 struct ceph_object_id src_oid, dst_oid;
19091928 loff_t endoff = 0, size;
@@ -1913,10 +1932,16 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, · 3 unmodified lines
19131932 int src_got = 0, dst_got = 0, err, dirty;
19141933 bool do_final_copy = false;
19151934
1916− if (src_inode == dst_inode)
1917− return -EINVAL;
1918− if (src_inode->i_sb != dst_inode->i_sb)
1919− return -EXDEV;
1935+ if (src_inode->i_sb != dst_inode->i_sb) {
1936+ struct ceph_fs_client *dst_fsc = ceph_inode_to_client(dst_inode);
1937+
1938+ if (ceph_fsid_compare(&src_fsc->client->fsid,
1939+ &dst_fsc->client->fsid)) {
1940+ dout("Copying files across clusters: src: %pU dst: %pU\n",
1941+ &src_fsc->client->fsid, &dst_fsc->client->fsid);
1942+ return -EXDEV;
1943+ }
1944+ }
19201945 if (ceph_snap(dst_inode) != CEPH_NOSNAP)
19211946 return -EROFS;
19221947
@@ -1928,7 +1953,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, · 5 unmodified lines
19281953 * efficient).
19291954 */
19301955
1931− if (ceph_test_mount_opt(ceph_inode_to_client(src_inode), NOCOPYFROM))
1956+ if (ceph_test_mount_opt(src_fsc, NOCOPYFROM))
19321957 return -EOPNOTSUPP;
19331958
19341959 if ((src_ci->i_layout.stripe_unit != dst_ci->i_layout.stripe_unit) ||
@@ -1960,8 +1985,8 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, · 25 unmodified lines
19601985 * clients may have dirty data in their caches. And OSDs know nothing
19611986 * about caps, so they can't safely do the remote object copies.
19621987 */
1963− err = get_rd_wr_caps(src_ci, (src_off + len), &src_got,
1964− dst_ci, (dst_off + len), &dst_got);
1988+ err = get_rd_wr_caps(src_file, &src_got,
1989+ dst_file, (dst_off + len), &dst_got);
19651990 if (err < 0) {
19661991 dout("get_rd_wr_caps returned %d\n", err);
19671992 ret = -EOPNOTSUPP;
@@ -2018,9 +2043,8 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, · 50 unmodified lines
20182043 goto out;
20192044 }
20202045 len -= ret;
2021− err = get_rd_wr_caps(src_ci, (src_off + len),
2022− &src_got, dst_ci,
2023− (dst_off + len), &dst_got);
2046+ err = get_rd_wr_caps(src_file, &src_got,
2047+ dst_file, (dst_off + len), &dst_got);
20242048 if (err < 0)
20252049 goto out;
20262050 err = is_file_size_ok(src_inode, dst_inode,
@@ -2044,7 +2068,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, · 17 unmodified lines
20442068 dst_ci->i_vino.ino, dst_objnum);
20452069 /* Do an object remote copy */
20462070 err = ceph_osdc_copy_from(
2047− &ceph_inode_to_client(src_inode)->client->osdc,
2071+ &src_fsc->client->osdc,
20482072 src_ci->i_vino.snap, 0,
20492073 &src_oid, &src_oloc,
20502074 CEPH_OSD_OP_FLAG_FADVISE_SEQUENTIAL |
fs/ceph/inode.c+29−21
@@ -515,6 +515,8 @@ struct inode *ceph_alloc_inode(struct super_block *sb) · 514 unmodified lines
515515
516516 ceph_fscache_inode_init(ci);
517517
518+ ci->i_meta_err = 0;
519+
518520 return &ci->vfs_inode;
519521 }
520522
@@ -801,7 +803,12 @@ static int fill_inode(struct inode *inode, struct page *locked_page, · 280 unmodified lines
801803
802804 /* update inode */
803805 inode->i_rdev = le32_to_cpu(info->rdev);
804− inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1;
806+ /* directories have fl_stripe_unit set to zero */
807+ if (le32_to_cpu(info->layout.fl_stripe_unit))
808+ inode->i_blkbits =
809+ fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1;
810+ else
811+ inode->i_blkbits = CEPH_BLOCK_SHIFT;
805812
806813 __ceph_update_quota(ci, iinfo->max_bytes, iinfo->max_files);
807814
@@ -1982,7 +1989,7 @@ static const struct inode_operations ceph_symlink_iops = { · 1174 unmodified lines
19821989 int __ceph_setattr(struct inode *inode, struct iattr *attr)
19831990 {
19841991 struct ceph_inode_info *ci = ceph_inode(inode);
1985− const unsigned int ia_valid = attr->ia_valid;
1992+ unsigned int ia_valid = attr->ia_valid;
19861993 struct ceph_mds_request *req;
19871994 struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
19881995 struct ceph_cap_flush *prealloc_cf;
@@ -2087,6 +2094,26 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr) · 98 unmodified lines
20872094 CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
20882095 }
20892096 }
2097+ if (ia_valid & ATTR_SIZE) {
2098+ dout("setattr %p size %lld -> %lld\n", inode,
2099+ inode->i_size, attr->ia_size);
2100+ if ((issued & CEPH_CAP_FILE_EXCL) &&
2101+ attr->ia_size > inode->i_size) {
2102+ i_size_write(inode, attr->ia_size);
2103+ inode->i_blocks = calc_inode_blocks(attr->ia_size);
2104+ ci->i_reported_size = attr->ia_size;
2105+ dirtied |= CEPH_CAP_FILE_EXCL;
2106+ ia_valid |= ATTR_MTIME;
2107+ } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
2108+ attr->ia_size != inode->i_size) {
2109+ req->r_args.setattr.size = cpu_to_le64(attr->ia_size);
2110+ req->r_args.setattr.old_size =
2111+ cpu_to_le64(inode->i_size);
2112+ mask |= CEPH_SETATTR_SIZE;
2113+ release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL |
2114+ CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
2115+ }
2116+ }
20902117 if (ia_valid & ATTR_MTIME) {
20912118 dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode,
20922119 inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
@@ -2109,25 +2136,6 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr) · 16 unmodified lines
21092136 CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
21102137 }
21112138 }
2112− if (ia_valid & ATTR_SIZE) {
2113− dout("setattr %p size %lld -> %lld\n", inode,
2114− inode->i_size, attr->ia_size);
2115− if ((issued & CEPH_CAP_FILE_EXCL) &&
2116− attr->ia_size > inode->i_size) {
2117− i_size_write(inode, attr->ia_size);
2118− inode->i_blocks = calc_inode_blocks(attr->ia_size);
2119− ci->i_reported_size = attr->ia_size;
2120− dirtied |= CEPH_CAP_FILE_EXCL;
2121− } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
2122− attr->ia_size != inode->i_size) {
2123− req->r_args.setattr.size = cpu_to_le64(attr->ia_size);
2124− req->r_args.setattr.old_size =
2125− cpu_to_le64(inode->i_size);
2126− mask |= CEPH_SETATTR_SIZE;
2127− release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL |
2128− CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
2129− }
2130− }
21312139
21322140 /* these do nothing */
21332141 if (ia_valid & ATTR_CTIME) {
fs/ceph/io.c+163−0
@@ -0,0 +1,163 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Copyright (c) 2016 Trond Myklebust
4+ * Copyright (c) 2019 Jeff Layton
5+ *
6+ * I/O and data path helper functionality.
7+ *
8+ * Heavily borrowed from equivalent code in fs/nfs/io.c
9+ */
10+
11+#include <linux/ceph/ceph_debug.h>
12+
13+#include <linux/types.h>
14+#include <linux/kernel.h>
15+#include <linux/rwsem.h>
16+#include <linux/fs.h>
17+
18+#include "super.h"
19+#include "io.h"
20+
21+/* Call with exclusively locked inode->i_rwsem */
22+static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode)
23+{
24+ lockdep_assert_held_write(&inode->i_rwsem);
25+
26+ if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) {
27+ spin_lock(&ci->i_ceph_lock);
28+ ci->i_ceph_flags &= ~CEPH_I_ODIRECT;
29+ spin_unlock(&ci->i_ceph_lock);
30+ inode_dio_wait(inode);
31+ }
32+}
33+
34+/**
35+ * ceph_start_io_read - declare the file is being used for buffered reads
36+ * @inode: file inode
37+ *
38+ * Declare that a buffered read operation is about to start, and ensure
39+ * that we block all direct I/O.
40+ * On exit, the function ensures that the CEPH_I_ODIRECT flag is unset,
41+ * and holds a shared lock on inode->i_rwsem to ensure that the flag
42+ * cannot be changed.
43+ * In practice, this means that buffered read operations are allowed to
44+ * execute in parallel, thanks to the shared lock, whereas direct I/O
45+ * operations need to wait to grab an exclusive lock in order to set
46+ * CEPH_I_ODIRECT.
47+ * Note that buffered writes and truncates both take a write lock on
48+ * inode->i_rwsem, meaning that those are serialised w.r.t. the reads.
49+ */
50+void
51+ceph_start_io_read(struct inode *inode)
52+{
53+ struct ceph_inode_info *ci = ceph_inode(inode);
54+
55+ /* Be an optimist! */
56+ down_read(&inode->i_rwsem);
57+ if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT))
58+ return;
59+ up_read(&inode->i_rwsem);
60+ /* Slow path.... */
61+ down_write(&inode->i_rwsem);
62+ ceph_block_o_direct(ci, inode);
63+ downgrade_write(&inode->i_rwsem);
64+}
65+
66+/**
67+ * ceph_end_io_read - declare that the buffered read operation is done
68+ * @inode: file inode
69+ *
70+ * Declare that a buffered read operation is done, and release the shared
71+ * lock on inode->i_rwsem.
72+ */
73+void
74+ceph_end_io_read(struct inode *inode)
75+{
76+ up_read(&inode->i_rwsem);
77+}
78+
79+/**
80+ * ceph_start_io_write - declare the file is being used for buffered writes
81+ * @inode: file inode
82+ *
83+ * Declare that a buffered write operation is about to start, and ensure
84+ * that we block all direct I/O.
85+ */
86+void
87+ceph_start_io_write(struct inode *inode)
88+{
89+ down_write(&inode->i_rwsem);
90+ ceph_block_o_direct(ceph_inode(inode), inode);
91+}
92+
93+/**
94+ * ceph_end_io_write - declare that the buffered write operation is done
95+ * @inode: file inode
96+ *
97+ * Declare that a buffered write operation is done, and release the
98+ * lock on inode->i_rwsem.
99+ */
100+void
101+ceph_end_io_write(struct inode *inode)
102+{
103+ up_write(&inode->i_rwsem);
104+}
105+
106+/* Call with exclusively locked inode->i_rwsem */
107+static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode)
108+{
109+ lockdep_assert_held_write(&inode->i_rwsem);
110+
111+ if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) {
112+ spin_lock(&ci->i_ceph_lock);
113+ ci->i_ceph_flags |= CEPH_I_ODIRECT;
114+ spin_unlock(&ci->i_ceph_lock);
115+ /* FIXME: unmap_mapping_range? */
116+ filemap_write_and_wait(inode->i_mapping);
117+ }
118+}
119+
120+/**
121+ * ceph_end_io_direct - declare the file is being used for direct i/o
122+ * @inode: file inode
123+ *
124+ * Declare that a direct I/O operation is about to start, and ensure
125+ * that we block all buffered I/O.
126+ * On exit, the function ensures that the CEPH_I_ODIRECT flag is set,
127+ * and holds a shared lock on inode->i_rwsem to ensure that the flag
128+ * cannot be changed.
129+ * In practice, this means that direct I/O operations are allowed to
130+ * execute in parallel, thanks to the shared lock, whereas buffered I/O
131+ * operations need to wait to grab an exclusive lock in order to clear
132+ * CEPH_I_ODIRECT.
133+ * Note that buffered writes and truncates both take a write lock on
134+ * inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT.
135+ */
136+void
137+ceph_start_io_direct(struct inode *inode)
138+{
139+ struct ceph_inode_info *ci = ceph_inode(inode);
140+
141+ /* Be an optimist! */
142+ down_read(&inode->i_rwsem);
143+ if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)
144+ return;
145+ up_read(&inode->i_rwsem);
146+ /* Slow path.... */
147+ down_write(&inode->i_rwsem);
148+ ceph_block_buffered(ci, inode);
149+ downgrade_write(&inode->i_rwsem);
150+}
151+
152+/**
153+ * ceph_end_io_direct - declare that the direct i/o operation is done
154+ * @inode: file inode
155+ *
156+ * Declare that a direct I/O operation is done, and release the shared
157+ * lock on inode->i_rwsem.
158+ */
159+void
160+ceph_end_io_direct(struct inode *inode)
161+{
162+ up_read(&inode->i_rwsem);
163+}
fs/ceph/io.h+12−0
@@ -0,0 +1,12 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+#ifndef _FS_CEPH_IO_H
3+#define _FS_CEPH_IO_H
4+
5+void ceph_start_io_read(struct inode *inode);
6+void ceph_end_io_read(struct inode *inode);
7+void ceph_start_io_write(struct inode *inode);
8+void ceph_end_io_write(struct inode *inode);
9+void ceph_start_io_direct(struct inode *inode);
10+void ceph_end_io_direct(struct inode *inode);
11+
12+#endif /* FS_CEPH_IO_H */
fs/ceph/locks.c+6−2
@@ -32,14 +32,18 @@ void __init ceph_flock_init(void) · 31 unmodified lines
3232
3333 static void ceph_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
3434 {
35− struct inode *inode = file_inode(src->fl_file);
35+ struct ceph_file_info *fi = dst->fl_file->private_data;
36+ struct inode *inode = file_inode(dst->fl_file);
3637 atomic_inc(&ceph_inode(inode)->i_filelock_ref);
38+ atomic_inc(&fi->num_locks);
3739 }
3840
3941 static void ceph_fl_release_lock(struct file_lock *fl)
4042 {
43+ struct ceph_file_info *fi = fl->fl_file->private_data;
4144 struct inode *inode = file_inode(fl->fl_file);
4245 struct ceph_inode_info *ci = ceph_inode(inode);
46+ atomic_dec(&fi->num_locks);
4347 if (atomic_dec_and_test(&ci->i_filelock_ref)) {
4448 /* clear error when all locks are released */
4549 spin_lock(&ci->i_ceph_lock);
@@ -73,7 +77,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode, · 27 unmodified lines
7377 * window. Caller function will decrease the counter.
7478 */
7579 fl->fl_ops = &ceph_fl_lock_ops;
76− atomic_inc(&ceph_inode(inode)->i_filelock_ref);
80+ fl->fl_ops->fl_copy_lock(fl, NULL);
7781 }
7882
7983 if (operation != CEPH_MDS_OP_SETFILELOCK || cmd == CEPH_LOCK_UNLOCK)
fs/ceph/mds_client.c+82−28
@@ -639,7 +639,6 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, · 638 unmodified lines
639639 s->s_renew_seq = 0;
640640 INIT_LIST_HEAD(&s->s_caps);
641641 s->s_nr_caps = 0;
642− s->s_trim_caps = 0;
643642 refcount_set(&s->s_ref, 1);
644643 INIT_LIST_HEAD(&s->s_waiting);
645644 INIT_LIST_HEAD(&s->s_unsafe);
@@ -1270,6 +1269,7 @@ static void cleanup_session_requests(struct ceph_mds_client *mdsc, · 624 unmodified lines
12701269 {
12711270 struct ceph_mds_request *req;
12721271 struct rb_node *p;
1272+ struct ceph_inode_info *ci;
12731273
12741274 dout("cleanup_session_requests mds%d\n", session->s_mds);
12751275 mutex_lock(&mdsc->mutex);
@@ -1278,6 +1278,16 @@ static void cleanup_session_requests(struct ceph_mds_client *mdsc, · 2 unmodified lines
12781278 struct ceph_mds_request, r_unsafe_item);
12791279 pr_warn_ratelimited(" dropping unsafe request %llu\n",
12801280 req->r_tid);
1281+ if (req->r_target_inode) {
1282+ /* dropping unsafe change of inode's attributes */
1283+ ci = ceph_inode(req->r_target_inode);
1284+ errseq_set(&ci->i_meta_err, -EIO);
1285+ }
1286+ if (req->r_unsafe_dir) {
1287+ /* dropping unsafe directory operation */
1288+ ci = ceph_inode(req->r_unsafe_dir);
1289+ errseq_set(&ci->i_meta_err, -EIO);
1290+ }
12811291 __unregister_request(mdsc, req);
12821292 }
12831293 /* zero r_attempts, so kick_requests() will re-send requests */
@@ -1370,7 +1380,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, · 86 unmodified lines
13701380 struct ceph_fs_client *fsc = (struct ceph_fs_client *)arg;
13711381 struct ceph_inode_info *ci = ceph_inode(inode);
13721382 LIST_HEAD(to_remove);
1373− bool drop = false;
1383+ bool dirty_dropped = false;
13741384 bool invalidate = false;
13751385
13761386 dout("removing cap %p, ci is %p, inode is %p\n",
@@ -1383,9 +1393,12 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, · 6 unmodified lines
13831393 struct ceph_cap_flush *cf;
13841394 struct ceph_mds_client *mdsc = fsc->mdsc;
13851395
1386− if (ci->i_wrbuffer_ref > 0 &&
1387− READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN)
1388− invalidate = true;
1396+ if (READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
1397+ if (inode->i_data.nrpages > 0)
1398+ invalidate = true;
1399+ if (ci->i_wrbuffer_ref > 0)
1400+ mapping_set_error(&inode->i_data, -EIO);
1401+ }
13891402
13901403 while (!list_empty(&ci->i_cap_flush_list)) {
13911404 cf = list_first_entry(&ci->i_cap_flush_list,
@@ -1405,7 +1418,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, · 13 unmodified lines
14051418 inode, ceph_ino(inode));
14061419 ci->i_dirty_caps = 0;
14071420 list_del_init(&ci->i_dirty_item);
1408− drop = true;
1421+ dirty_dropped = true;
14091422 }
14101423 if (!list_empty(&ci->i_flushing_item)) {
14111424 pr_warn_ratelimited(
@@ -1415,10 +1428,22 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, · 3 unmodified lines
14151428 ci->i_flushing_caps = 0;
14161429 list_del_init(&ci->i_flushing_item);
14171430 mdsc->num_cap_flushing--;
1418− drop = true;
1431+ dirty_dropped = true;
14191432 }
14201433 spin_unlock(&mdsc->cap_dirty_lock);
14211434
1435+ if (dirty_dropped) {
1436+ errseq_set(&ci->i_meta_err, -EIO);
1437+
1438+ if (ci->i_wrbuffer_ref_head == 0 &&
1439+ ci->i_wr_ref == 0 &&
1440+ ci->i_dirty_caps == 0 &&
1441+ ci->i_flushing_caps == 0) {
1442+ ceph_put_snap_context(ci->i_head_snapc);
1443+ ci->i_head_snapc = NULL;
1444+ }
1445+ }
1446+
14221447 if (atomic_read(&ci->i_filelock_ref) > 0) {
14231448 /* make further file lock syscall return -EIO */
14241449 ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
@@ -1430,15 +1455,6 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, · 5 unmodified lines
14301455 list_add(&ci->i_prealloc_cap_flush->i_list, &to_remove);
14311456 ci->i_prealloc_cap_flush = NULL;
14321457 }
1433−
1434− if (drop &&
1435− ci->i_wrbuffer_ref_head == 0 &&
1436− ci->i_wr_ref == 0 &&
1437− ci->i_dirty_caps == 0 &&
1438− ci->i_flushing_caps == 0) {
1439− ceph_put_snap_context(ci->i_head_snapc);
1440− ci->i_head_snapc = NULL;
1441− }
14421458 }
14431459 spin_unlock(&ci->i_ceph_lock);
14441460 while (!list_empty(&to_remove)) {
@@ -1452,7 +1468,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, · 7 unmodified lines
14521468 wake_up_all(&ci->i_cap_wq);
14531469 if (invalidate)
14541470 ceph_queue_invalidate(inode);
1455− if (drop)
1471+ if (dirty_dropped)
14561472 iput(inode);
14571473 return 0;
14581474 }
@@ -1705,11 +1721,11 @@ out: · 246 unmodified lines
17051721 */
17061722 static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
17071723 {
1708− struct ceph_mds_session *session = arg;
1724+ int *remaining = arg;
17091725 struct ceph_inode_info *ci = ceph_inode(inode);
17101726 int used, wanted, oissued, mine;
17111727
1712− if (session->s_trim_caps <= 0)
1728+ if (*remaining <= 0)
17131729 return -1;
17141730
17151731 spin_lock(&ci->i_ceph_lock);
@@ -1746,7 +1762,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) · 30 unmodified lines
17461762 if (oissued) {
17471763 /* we aren't the only cap.. just remove us */
17481764 __ceph_remove_cap(cap, true);
1749− session->s_trim_caps--;
1765+ (*remaining)--;
17501766 } else {
17511767 struct dentry *dentry;
17521768 /* try dropping referring dentries */
@@ -1758,7 +1774,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) · 5 unmodified lines
17581774 d_prune_aliases(inode);
17591775 count = atomic_read(&inode->i_count);
17601776 if (count == 1)
1761− session->s_trim_caps--;
1777+ (*remaining)--;
17621778 dout("trim_caps_cb %p cap %p pruned, count now %d\n",
17631779 inode, cap, count);
17641780 } else {
@@ -1784,12 +1800,12 @@ int ceph_trim_caps(struct ceph_mds_client *mdsc, · 19 unmodified lines
17841800 dout("trim_caps mds%d start: %d / %d, trim %d\n",
17851801 session->s_mds, session->s_nr_caps, max_caps, trim_caps);
17861802 if (trim_caps > 0) {
1787− session->s_trim_caps = trim_caps;
1788− ceph_iterate_session_caps(session, trim_caps_cb, session);
1803+ int remaining = trim_caps;
1804+
1805+ ceph_iterate_session_caps(session, trim_caps_cb, &remaining);
17891806 dout("trim_caps mds%d done: %d / %d, trimmed %d\n",
17901807 session->s_mds, session->s_nr_caps, max_caps,
1791− trim_caps - session->s_trim_caps);
1792− session->s_trim_caps = 0;
1808+ trim_caps - remaining);
17931809 }
17941810
17951811 ceph_flush_cap_releases(mdsc, session);
@@ -3015,18 +3031,23 @@ bad: · 1219 unmodified lines
30153031 pr_err("mdsc_handle_forward decode error err=%d\n", err);
30163032 }
30173033
3018−static int __decode_and_drop_session_metadata(void **p, void *end)
3034+static int __decode_session_metadata(void **p, void *end,
3035+ bool *blacklisted)
30193036 {
30203037 /* map<string,string> */
30213038 u32 n;
3039+ bool err_str;
30223040 ceph_decode_32_safe(p, end, n, bad);
30233041 while (n-- > 0) {
30243042 u32 len;
30253043 ceph_decode_32_safe(p, end, len, bad);
30263044 ceph_decode_need(p, end, len, bad);
3045+ err_str = !strncmp(*p, "error_string", len);
30273046 *p += len;
30283047 ceph_decode_32_safe(p, end, len, bad);
30293048 ceph_decode_need(p, end, len, bad);
3049+ if (err_str && strnstr(*p, "blacklisted", len))
3050+ *blacklisted = true;
30303051 *p += len;
30313052 }
30323053 return 0;
@@ -3050,6 +3071,7 @@ static void handle_session(struct ceph_mds_session *session, · 17 unmodified lines
30503071 u64 seq;
30513072 unsigned long features = 0;
30523073 int wake = 0;
3074+ bool blacklisted = false;
30533075
30543076 /* decode */
30553077 ceph_decode_need(&p, end, sizeof(*h), bad);
@@ -3062,7 +3084,7 @@ static void handle_session(struct ceph_mds_session *session, · 6 unmodified lines
30623084 if (msg_version >= 3) {
30633085 u32 len;
30643086 /* version >= 2, metadata */
3065− if (__decode_and_drop_session_metadata(&p, end) < 0)
3087+ if (__decode_session_metadata(&p, end, &blacklisted) < 0)
30663088 goto bad;
30673089 /* version >= 3, feature bits */
30683090 ceph_decode_32_safe(&p, end, len, bad);
@@ -3149,6 +3171,8 @@ static void handle_session(struct ceph_mds_session *session, · 80 unmodified lines
31493171 session->s_state = CEPH_MDS_SESSION_REJECTED;
31503172 cleanup_session_requests(mdsc, session);
31513173 remove_session_caps(session);
3174+ if (blacklisted)
3175+ mdsc->fsc->blacklisted = true;
31523176 wake = 2; /* for good measure */
31533177 break;
31543178
@@ -3998,7 +4022,27 @@ static void lock_unlock_sessions(struct ceph_mds_client *mdsc) · 843 unmodified lines
39984022 mutex_unlock(&mdsc->mutex);
39994023 }
40004024
4025+static void maybe_recover_session(struct ceph_mds_client *mdsc)
4026+{
4027+ struct ceph_fs_client *fsc = mdsc->fsc;
4028+
4029+ if (!ceph_test_mount_opt(fsc, CLEANRECOVER))
4030+ return;
4031+
4032+ if (READ_ONCE(fsc->mount_state) != CEPH_MOUNT_MOUNTED)
4033+ return;
4034+
4035+ if (!READ_ONCE(fsc->blacklisted))
4036+ return;
4037+
4038+ if (fsc->last_auto_reconnect &&
4039+ time_before(jiffies, fsc->last_auto_reconnect + HZ * 60 * 30))
4040+ return;
40014041
4042+ pr_info("auto reconnect after blacklisted\n");
4043+ fsc->last_auto_reconnect = jiffies;
4044+ ceph_force_reconnect(fsc->sb);
4045+}
40024046
40034047 /*
40044048 * delayed work -- periodically trim expired leases, renew caps with mds
@@ -4044,7 +4088,9 @@ static void delayed_work(struct work_struct *work) · 39 unmodified lines
40444088 pr_info("mds%d hung\n", s->s_mds);
40454089 }
40464090 }
4047− if (s->s_state < CEPH_MDS_SESSION_OPEN) {
4091+ if (s->s_state == CEPH_MDS_SESSION_NEW ||
4092+ s->s_state == CEPH_MDS_SESSION_RESTARTING ||
4093+ s->s_state == CEPH_MDS_SESSION_REJECTED) {
40484094 /* this mds is failed or recovering, just wait */
40494095 ceph_put_mds_session(s);
40504096 continue;
@@ -4072,6 +4118,8 @@ static void delayed_work(struct work_struct *work) · 21 unmodified lines
40724118
40734119 ceph_trim_snapid_map(mdsc);
40744120
4121+ maybe_recover_session(mdsc);
4122+
40754123 schedule_delayed(mdsc);
40764124 }
40774125
@@ -4355,7 +4403,12 @@ void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc) · 277 unmodified lines
43554403 session = __ceph_lookup_mds_session(mdsc, mds);
43564404 if (!session)
43574405 continue;
4406+
4407+ if (session->s_state == CEPH_MDS_SESSION_REJECTED)
4408+ __unregister_session(mdsc, session);
4409+ __wake_requests(mdsc, &session->s_waiting);
43584410 mutex_unlock(&mdsc->mutex);
4411+
43594412 mutex_lock(&session->s_mutex);
43604413 __close_session(mdsc, session);
43614414 if (session->s_state == CEPH_MDS_SESSION_CLOSING) {
@@ -4364,6 +4417,7 @@ void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc) · 2 unmodified lines
43644417 }
43654418 mutex_unlock(&session->s_mutex);
43664419 ceph_put_mds_session(session);
4420+
43674421 mutex_lock(&mdsc->mutex);
43684422 kick_requests(mdsc, mds);
43694423 }
fs/ceph/mds_client.h+4−4
@@ -148,9 +148,9 @@ enum { · 147 unmodified lines
148148 CEPH_MDS_SESSION_OPENING = 2,
149149 CEPH_MDS_SESSION_OPEN = 3,
150150 CEPH_MDS_SESSION_HUNG = 4,
151− CEPH_MDS_SESSION_CLOSING = 5,
152− CEPH_MDS_SESSION_RESTARTING = 6,
153− CEPH_MDS_SESSION_RECONNECTING = 7,
151+ CEPH_MDS_SESSION_RESTARTING = 5,
152+ CEPH_MDS_SESSION_RECONNECTING = 6,
153+ CEPH_MDS_SESSION_CLOSING = 7,
154154 CEPH_MDS_SESSION_REJECTED = 8,
155155 };
156156
@@ -176,7 +176,7 @@ struct ceph_mds_session { · 19 unmodified lines
176176 spinlock_t s_cap_lock;
177177 struct list_head s_caps; /* all caps issued by this session */
178178 struct ceph_cap *s_cap_iterator;
179− int s_nr_caps, s_trim_caps;
179+ int s_nr_caps;
180180 int s_num_cap_releases;
181181 int s_cap_reconnect;
182182 int s_readonly;
fs/ceph/super.c+47−5
@@ -143,6 +143,7 @@ enum { · 142 unmodified lines
143143 Opt_snapdirname,
144144 Opt_mds_namespace,
145145 Opt_fscache_uniq,
146+ Opt_recover_session,
146147 Opt_last_string,
147148 /* string args above */
148149 Opt_dirstat,
@@ -184,6 +185,7 @@ static match_table_t fsopt_tokens = { · 35 unmodified lines
184185 /* int args above */
185186 {Opt_snapdirname, "snapdirname=%s"},
186187 {Opt_mds_namespace, "mds_namespace=%s"},
188+ {Opt_recover_session, "recover_session=%s"},
187189 {Opt_fscache_uniq, "fsc=%s"},
188190 /* string args above */
189191 {Opt_dirstat, "dirstat"},
@@ -254,6 +256,17 @@ static int parse_fsopt_token(char *c, void *private) · 64 unmodified lines
254256 if (!fsopt->mds_namespace)
255257 return -ENOMEM;
256258 break;
259+ case Opt_recover_session:
260+ if (!strncmp(argstr[0].from, "no",
261+ argstr[0].to - argstr[0].from)) {
262+ fsopt->flags &= ~CEPH_MOUNT_OPT_CLEANRECOVER;
263+ } else if (!strncmp(argstr[0].from, "clean",
264+ argstr[0].to - argstr[0].from)) {
265+ fsopt->flags |= CEPH_MOUNT_OPT_CLEANRECOVER;
266+ } else {
267+ return -EINVAL;
268+ }
269+ break;
257270 case Opt_fscache_uniq:
258271 kfree(fsopt->fscache_uniq);
259272 fsopt->fscache_uniq = kstrndup(argstr[0].from,
@@ -576,6 +589,10 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) · 316 unmodified lines
576589
577590 if (fsopt->mds_namespace)
578591 seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
592+
593+ if (fsopt->flags & CEPH_MOUNT_OPT_CLEANRECOVER)
594+ seq_show_option(m, "recover_session", "clean");
595+
579596 if (fsopt->wsize != CEPH_MAX_WRITE_SIZE)
580597 seq_printf(m, ",wsize=%d", fsopt->wsize);
581598 if (fsopt->rsize != CEPH_MAX_READ_SIZE)
@@ -664,6 +681,7 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt, · 82 unmodified lines
664681
665682 fsc->sb = NULL;
666683 fsc->mount_state = CEPH_MOUNT_MOUNTING;
684+ fsc->filp_gen = 1;
667685
668686 atomic_long_set(&fsc->writeback_count, 0);
669687
@@ -713,6 +731,7 @@ static void destroy_fs_client(struct ceph_fs_client *fsc) · 43 unmodified lines
713731 {
714732 dout("destroy_fs_client %p\n", fsc);
715733
734+ ceph_mdsc_destroy(fsc);
716735 destroy_workqueue(fsc->inode_wq);
717736 destroy_workqueue(fsc->cap_wq);
718737
@@ -829,7 +848,7 @@ static void ceph_umount_begin(struct super_block *sb) · 110 unmodified lines
829848 fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
830849 ceph_osdc_abort_requests(&fsc->client->osdc, -EIO);
831850 ceph_mdsc_force_umount(fsc->mdsc);
832− return;
851+ fsc->filp_gen++; // invalidate open files
833852 }
834853
835854 static int ceph_remount(struct super_block *sb, int *flags, char *data)
@@ -1089,7 +1108,6 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type, · 253 unmodified lines
10891108 }
10901109
10911110 if (ceph_sb_to_client(sb) != fsc) {
1092− ceph_mdsc_destroy(fsc);
10931111 destroy_fs_client(fsc);
10941112 fsc = ceph_sb_to_client(sb);
10951113 dout("get_sb got existing client %p\n", fsc);
@@ -1115,7 +1133,6 @@ out_splat: · 19 unmodified lines
11151133 goto out_final;
11161134
11171135 out:
1118− ceph_mdsc_destroy(fsc);
11191136 destroy_fs_client(fsc);
11201137 out_final:
11211138 dout("ceph_mount fail %ld\n", PTR_ERR(res));
@@ -1139,8 +1156,6 @@ static void ceph_kill_sb(struct super_block *s) · 17 unmodified lines
11391156
11401157 ceph_fscache_unregister_fs(fsc);
11411158
1142− ceph_mdsc_destroy(fsc);
1143−
11441159 destroy_fs_client(fsc);
11451160 free_anon_bdev(dev);
11461161 }
@@ -1154,6 +1169,33 @@ static struct file_system_type ceph_fs_type = { · 7 unmodified lines
11541169 };
11551170 MODULE_ALIAS_FS("ceph");
11561171
1172+int ceph_force_reconnect(struct super_block *sb)
1173+{
1174+ struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
1175+ int err = 0;
1176+
1177+ ceph_umount_begin(sb);
1178+
1179+ /* Make sure all page caches get invalidated.
1180+ * see remove_session_caps_cb() */
1181+ flush_workqueue(fsc->inode_wq);
1182+
1183+ /* In case that we were blacklisted. This also reset
1184+ * all mon/osd connections */
1185+ ceph_reset_client_addr(fsc->client);
1186+
1187+ ceph_osdc_clear_abort_err(&fsc->client->osdc);
1188+
1189+ fsc->blacklisted = false;
1190+ fsc->mount_state = CEPH_MOUNT_MOUNTED;
1191+
1192+ if (sb->s_root) {
1193+ err = __ceph_do_getattr(d_inode(sb->s_root), NULL,
1194+ CEPH_STAT_CAP_INODE, true);
1195+ }
1196+ return err;
1197+}
1198+
11571199 static int __init init_ceph(void)
11581200 {
11591201 int ret = init_caches();
fs/ceph/super.h+32−17
@@ -16,6 +16,7 @@ · 15 unmodified lines
1616 #include <linux/slab.h>
1717 #include <linux/posix_acl.h>
1818 #include <linux/refcount.h>
19+#include <linux/security.h>
1920
2021 #include <linux/ceph/libceph.h>
2122
@@ -31,6 +32,7 @@ · 9 unmodified lines
3132 #define CEPH_BLOCK_SHIFT 22 /* 4 MB */
3233 #define CEPH_BLOCK (1 << CEPH_BLOCK_SHIFT)
3334
35+#define CEPH_MOUNT_OPT_CLEANRECOVER (1<<1) /* auto reonnect (clean mode) after blacklisted */
3436 #define CEPH_MOUNT_OPT_DIRSTAT (1<<4) /* `cat dirname` for stats */
3537 #define CEPH_MOUNT_OPT_RBYTES (1<<5) /* dir st_bytes = rbytes */
3638 #define CEPH_MOUNT_OPT_NOASYNCREADDIR (1<<7) /* no dcache readdir */
@@ -101,6 +103,11 @@ struct ceph_fs_client { · 64 unmodified lines
101103 struct ceph_client *client;
102104
103105 unsigned long mount_state;
106+
107+ unsigned long last_auto_reconnect;
108+ bool blacklisted;
109+
110+ u32 filp_gen;
104111 loff_t max_file_size;
105112
106113 struct ceph_mds_client *mdsc;
@@ -395,6 +402,8 @@ struct ceph_inode_info { · 288 unmodified lines
395402 struct fscache_cookie *fscache;
396403 u32 i_fscache_gen;
397404 #endif
405+ errseq_t i_meta_err;
406+
398407 struct inode vfs_inode; /* at end */
399408 };
400409
@@ -499,17 +508,16 @@ static inline struct inode *ceph_find_inode(struct super_block *sb, · 98 unmodified lines
499508 #define CEPH_I_DIR_ORDERED (1 << 0) /* dentries in dir are ordered */
500509 #define CEPH_I_NODELAY (1 << 1) /* do not delay cap release */
501510 #define CEPH_I_FLUSH (1 << 2) /* do not delay flush of dirty metadata */
502−#define CEPH_I_NOFLUSH (1 << 3) /* do not flush dirty caps */
503−#define CEPH_I_POOL_PERM (1 << 4) /* pool rd/wr bits are valid */
504−#define CEPH_I_POOL_RD (1 << 5) /* can read from pool */
505−#define CEPH_I_POOL_WR (1 << 6) /* can write to pool */
506−#define CEPH_I_SEC_INITED (1 << 7) /* security initialized */
507−#define CEPH_I_CAP_DROPPED (1 << 8) /* caps were forcibly dropped */
508−#define CEPH_I_KICK_FLUSH (1 << 9) /* kick flushing caps */
509−#define CEPH_I_FLUSH_SNAPS (1 << 10) /* need flush snapss */
510−#define CEPH_I_ERROR_WRITE (1 << 11) /* have seen write errors */
511−#define CEPH_I_ERROR_FILELOCK (1 << 12) /* have seen file lock errors */
512−
511+#define CEPH_I_POOL_PERM (1 << 3) /* pool rd/wr bits are valid */
512+#define CEPH_I_POOL_RD (1 << 4) /* can read from pool */
513+#define CEPH_I_POOL_WR (1 << 5) /* can write to pool */
514+#define CEPH_I_SEC_INITED (1 << 6) /* security initialized */
515+#define CEPH_I_CAP_DROPPED (1 << 7) /* caps were forcibly dropped */
516+#define CEPH_I_KICK_FLUSH (1 << 8) /* kick flushing caps */
517+#define CEPH_I_FLUSH_SNAPS (1 << 9) /* need flush snapss */
518+#define CEPH_I_ERROR_WRITE (1 << 10) /* have seen write errors */
519+#define CEPH_I_ERROR_FILELOCK (1 << 11) /* have seen file lock errors */
520+#define CEPH_I_ODIRECT (1 << 12) /* inode in direct I/O mode */
513521
514522 /*
515523 * Masks of ceph inode work.
@@ -703,6 +711,10 @@ struct ceph_file_info { · 187 unmodified lines
703711
704712 spinlock_t rw_contexts_lock;
705713 struct list_head rw_contexts;
714+
715+ errseq_t meta_err;
716+ u32 filp_gen;
717+ atomic_t num_locks;
706718 };
707719
708720 struct ceph_dir_file_info {
@@ -842,7 +854,8 @@ static inline int default_congestion_kb(void) · 133 unmodified lines
842854 }
843855
844856
845−
857+/* super.c */
858+extern int ceph_force_reconnect(struct super_block *sb);
846859 /* snap.c */
847860 struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc,
848861 u64 ino);
@@ -959,7 +972,10 @@ static inline bool ceph_security_xattr_wanted(struct inode *in) · 110 unmodified lines
959972 #ifdef CONFIG_CEPH_FS_SECURITY_LABEL
960973 extern int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
961974 struct ceph_acl_sec_ctx *ctx);
962−extern void ceph_security_invalidate_secctx(struct inode *inode);
975+static inline void ceph_security_invalidate_secctx(struct inode *inode)
976+{
977+ security_inode_invalidate_secctx(inode);
978+}
963979 #else
964980 static inline int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
965981 struct ceph_acl_sec_ctx *ctx)
@@ -1039,7 +1055,6 @@ extern void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, · 73 unmodified lines
10391055 struct ceph_mds_session *session);
10401056 extern struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci,
10411057 int mds);
1042−extern int ceph_get_cap_mds(struct inode *inode);
10431058 extern void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps);
10441059 extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had);
10451060 extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
@@ -1058,9 +1073,9 @@ extern int ceph_encode_dentry_release(void **p, struct dentry *dn, · 12 unmodified lines
10581073 struct inode *dir,
10591074 int mds, int drop, int unless);
10601075
1061−extern int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
1076+extern int ceph_get_caps(struct file *filp, int need, int want,
10621077 loff_t endoff, int *got, struct page **pinned_page);
1063−extern int ceph_try_get_caps(struct ceph_inode_info *ci,
1078+extern int ceph_try_get_caps(struct inode *inode,
10641079 int need, int want, bool nonblock, int *got);
10651080
10661081 /* for counting open files by mode */
@@ -1071,7 +1086,7 @@ extern void ceph_put_fmode(struct ceph_inode_info *ci, int mode); · 4 unmodified lines
10711086 extern const struct address_space_operations ceph_aops;
10721087 extern int ceph_mmap(struct file *file, struct vm_area_struct *vma);
10731088 extern int ceph_uninline_data(struct file *filp, struct page *locked_page);
1074−extern int ceph_pool_perm_check(struct ceph_inode_info *ci, int need);
1089+extern int ceph_pool_perm_check(struct inode *inode, int need);
10751090 extern void ceph_pool_perm_destroy(struct ceph_mds_client* mdsc);
10761091
10771092 /* file.c */
fs/ceph/xattr.c+6−70
@@ -20,7 +20,8 @@ static int __remove_xattr(struct ceph_inode_info *ci, · 19 unmodified lines
2020
2121 static bool ceph_is_valid_xattr(const char *name)
2222 {
23− return !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
23+ return !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
24+ !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
2425 !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
2526 !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
2627 }
@@ -892,7 +893,8 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, · 865 unmodified lines
892893 memcpy(value, xattr->val, xattr->val_len);
893894
894895 if (current->journal_info &&
895− !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN))
896+ !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
897+ security_ismaclabel(name + XATTR_SECURITY_PREFIX_LEN))
896898 ci->i_ceph_flags |= CEPH_I_SEC_INITED;
897899 out:
898900 spin_unlock(&ci->i_ceph_lock);
@@ -903,11 +905,9 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) · 4 unmodified lines
903905 {
904906 struct inode *inode = d_inode(dentry);
905907 struct ceph_inode_info *ci = ceph_inode(inode);
906− struct ceph_vxattr *vxattrs = ceph_inode_vxattrs(inode);
907908 bool len_only = (size == 0);
908909 u32 namelen;
909910 int err;
910− int i;
911911
912912 spin_lock(&ci->i_ceph_lock);
913913 dout("listxattr %p ver=%lld index_ver=%lld\n", inode,
@@ -936,33 +936,6 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) · 22 unmodified lines
936936 names = __copy_xattr_names(ci, names);
937937 size -= namelen;
938938 }
939−
940−
941− /* virtual xattr names, too */
942− if (vxattrs) {
943− for (i = 0; vxattrs[i].name; i++) {
944− size_t this_len;
945−
946− if (vxattrs[i].flags & VXATTR_FLAG_HIDDEN)
947− continue;
948− if (vxattrs[i].exists_cb && !vxattrs[i].exists_cb(ci))
949− continue;
950−
951− this_len = strlen(vxattrs[i].name) + 1;
952− namelen += this_len;
953− if (len_only)
954− continue;
955−
956− if (this_len > size) {
957− err = -ERANGE;
958− goto out;
959− }
960−
961− memcpy(names, vxattrs[i].name, this_len);
962− names += this_len;
963− size -= this_len;
964− }
965− }
966939 err = namelen;
967940 out:
968941 spin_unlock(&ci->i_ceph_lock);
@@ -1293,42 +1266,8 @@ out: · 324 unmodified lines
12931266 ceph_pagelist_release(pagelist);
12941267 return err;
12951268 }
1296−
1297−void ceph_security_invalidate_secctx(struct inode *inode)
1298−{
1299− security_inode_invalidate_secctx(inode);
1300−}
1301−
1302−static int ceph_xattr_set_security_label(const struct xattr_handler *handler,
1303− struct dentry *unused, struct inode *inode,
1304− const char *key, const void *buf,
1305− size_t buflen, int flags)
1306−{
1307− if (security_ismaclabel(key)) {
1308− const char *name = xattr_full_name(handler, key);
1309− return __ceph_setxattr(inode, name, buf, buflen, flags);
1310− }
1311− return -EOPNOTSUPP;
1312−}
1313−
1314−static int ceph_xattr_get_security_label(const struct xattr_handler *handler,
1315− struct dentry *unused, struct inode *inode,
1316− const char *key, void *buf, size_t buflen)
1317−{
1318− if (security_ismaclabel(key)) {
1319− const char *name = xattr_full_name(handler, key);
1320− return __ceph_getxattr(inode, name, buf, buflen);
1321− }
1322− return -EOPNOTSUPP;
1323−}
1324−
1325−static const struct xattr_handler ceph_security_label_handler = {
1326− .prefix = XATTR_SECURITY_PREFIX,
1327− .get = ceph_xattr_get_security_label,
1328− .set = ceph_xattr_set_security_label,
1329−};
1330−#endif
1331−#endif
1269+#endif /* CONFIG_CEPH_FS_SECURITY_LABEL */
1270+#endif /* CONFIG_SECURITY */
13321271
13331272 void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
13341273 {
@@ -1351,9 +1290,6 @@ const struct xattr_handler *ceph_xattr_handlers[] = { · 16 unmodified lines
13511290 #ifdef CONFIG_CEPH_FS_POSIX_ACL
13521291 &posix_acl_access_xattr_handler,
13531292 &posix_acl_default_xattr_handler,
1354−#endif
1355−#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
1356− &ceph_security_label_handler,
13571293 #endif
13581294 &ceph_other_xattr_handler,
13591295 NULL,
include/linux/ceph/libceph.h+1−0
@@ -293,6 +293,7 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private); · 292 unmodified lines
293293 struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client);
294294 u64 ceph_client_gid(struct ceph_client *client);
295295 extern void ceph_destroy_client(struct ceph_client *client);
296+extern void ceph_reset_client_addr(struct ceph_client *client);
296297 extern int __ceph_open_session(struct ceph_client *client,
297298 unsigned long started);
298299 extern int ceph_open_session(struct ceph_client *client);
include/linux/ceph/messenger.h+1−0
@@ -337,6 +337,7 @@ extern void ceph_msgr_flush(void); · 336 unmodified lines
337337 extern void ceph_messenger_init(struct ceph_messenger *msgr,
338338 struct ceph_entity_addr *myaddr);
339339 extern void ceph_messenger_fini(struct ceph_messenger *msgr);
340+extern void ceph_messenger_reset_nonce(struct ceph_messenger *msgr);
340341
341342 extern void ceph_con_init(struct ceph_connection *con, void *private,
342343 const struct ceph_connection_operations *ops,
include/linux/ceph/mon_client.h+1−0
@@ -109,6 +109,7 @@ extern int ceph_monmap_contains(struct ceph_monmap *m, · 108 unmodified lines
109109
110110 extern int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl);
111111 extern void ceph_monc_stop(struct ceph_mon_client *monc);
112+extern void ceph_monc_reopen_session(struct ceph_mon_client *monc);
112113
113114 enum {
114115 CEPH_SUB_MONMAP = 0,
include/linux/ceph/osd_client.h+2−0
@@ -381,6 +381,7 @@ extern void ceph_osdc_cleanup(void); · 380 unmodified lines
381381 extern int ceph_osdc_init(struct ceph_osd_client *osdc,
382382 struct ceph_client *client);
383383 extern void ceph_osdc_stop(struct ceph_osd_client *osdc);
384+extern void ceph_osdc_reopen_osds(struct ceph_osd_client *osdc);
384385
385386 extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc,
386387 struct ceph_msg *msg);
@@ -388,6 +389,7 @@ extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc, · 1 unmodified line
388389 struct ceph_msg *msg);
389390 void ceph_osdc_update_epoch_barrier(struct ceph_osd_client *osdc, u32 eb);
390391 void ceph_osdc_abort_requests(struct ceph_osd_client *osdc, int err);
392+void ceph_osdc_clear_abort_err(struct ceph_osd_client *osdc);
391393
392394 #define osd_req_op_data(oreq, whch, typ, fld) \
393395 ({ \
net/ceph/ceph_common.c+31−6
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 #include <linux/nsproxy.h>
1414 #include <linux/parser.h>
1515 #include <linux/sched.h>
16+#include <linux/sched/mm.h>
1617 #include <linux/seq_file.h>
1718 #include <linux/slab.h>
1819 #include <linux/statfs.h>
@@ -185,18 +186,34 @@ int ceph_compare_options(struct ceph_options *new_opt, · 166 unmodified lines
185186 }
186187 EXPORT_SYMBOL(ceph_compare_options);
187188
189+/*
190+ * kvmalloc() doesn't fall back to the vmalloc allocator unless flags are
191+ * compatible with (a superset of) GFP_KERNEL. This is because while the
192+ * actual pages are allocated with the specified flags, the page table pages
193+ * are always allocated with GFP_KERNEL. map_vm_area() doesn't even take
194+ * flags because GFP_KERNEL is hard-coded in {p4d,pud,pmd,pte}_alloc().
195+ *
196+ * ceph_kvmalloc() may be called with GFP_KERNEL, GFP_NOFS or GFP_NOIO.
197+ */
188198 void *ceph_kvmalloc(size_t size, gfp_t flags)
189199 {
190− if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
191− void *ptr = kmalloc(size, flags | __GFP_NOWARN);
192− if (ptr)
193− return ptr;
200+ void *p;
201+
202+ if ((flags & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS)) {
203+ p = kvmalloc(size, flags);
204+ } else if ((flags & (__GFP_IO | __GFP_FS)) == __GFP_IO) {
205+ unsigned int nofs_flag = memalloc_nofs_save();
206+ p = kvmalloc(size, GFP_KERNEL);
207+ memalloc_nofs_restore(nofs_flag);
208+ } else {
209+ unsigned int noio_flag = memalloc_noio_save();
210+ p = kvmalloc(size, GFP_KERNEL);
211+ memalloc_noio_restore(noio_flag);
194212 }
195213
196− return __vmalloc(size, flags, PAGE_KERNEL);
214+ return p;
197215 }
198216
199−
200217 static int parse_fsid(const char *str, struct ceph_fsid *fsid)
201218 {
202219 int i = 0;
@@ -694,6 +711,14 @@ void ceph_destroy_client(struct ceph_client *client) · 491 unmodified lines
694711 }
695712 EXPORT_SYMBOL(ceph_destroy_client);
696713
714+void ceph_reset_client_addr(struct ceph_client *client)
715+{
716+ ceph_messenger_reset_nonce(&client->msgr);
717+ ceph_monc_reopen_session(&client->monc);
718+ ceph_osdc_reopen_osds(&client->osdc);
719+}
720+EXPORT_SYMBOL(ceph_reset_client_addr);
721+
697722 /*
698723 * true if we have the mon map (and have thus joined the cluster)
699724 */
net/ceph/messenger.c+6−0
@@ -3031,6 +3031,12 @@ static void con_fault(struct ceph_connection *con) · 3030 unmodified lines
30313031 }
30323032
30333033
3034+void ceph_messenger_reset_nonce(struct ceph_messenger *msgr)
3035+{
3036+ u32 nonce = le32_to_cpu(msgr->inst.addr.nonce) + 1000000;
3037+ msgr->inst.addr.nonce = cpu_to_le32(nonce);
3038+ encode_my_addr(msgr);
3039+}
30343040
30353041 /*
30363042 * initialize a new messenger instance
net/ceph/mon_client.c+7−0
@@ -213,6 +213,13 @@ static void reopen_session(struct ceph_mon_client *monc) · 212 unmodified lines
213213 __open_session(monc);
214214 }
215215
216+void ceph_monc_reopen_session(struct ceph_mon_client *monc)
217+{
218+ mutex_lock(&monc->mutex);
219+ reopen_session(monc);
220+ mutex_unlock(&monc->mutex);
221+}
222+
216223 static void un_backoff(struct ceph_mon_client *monc)
217224 {
218225 monc->hunt_mult /= 2; /* reduce by 50% */
net/ceph/osd_client.c+53−12
@@ -841,6 +841,7 @@ int osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which, · 840 unmodified lines
841841 struct ceph_pagelist *pagelist;
842842 size_t payload_len = 0;
843843 size_t size;
844+ int ret;
844845
845846 op = _osd_req_op_init(osd_req, which, CEPH_OSD_OP_CALL, 0);
846847
@@ -852,20 +853,27 @@ int osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which, · 5 unmodified lines
852853 size = strlen(class);
853854 BUG_ON(size > (size_t) U8_MAX);
854855 op->cls.class_len = size;
855− ceph_pagelist_append(pagelist, class, size);
856+ ret = ceph_pagelist_append(pagelist, class, size);
857+ if (ret)
858+ goto err_pagelist_free;
856859 payload_len += size;
857860
858861 op->cls.method_name = method;
859862 size = strlen(method);
860863 BUG_ON(size > (size_t) U8_MAX);
861864 op->cls.method_len = size;
862− ceph_pagelist_append(pagelist, method, size);
865+ ret = ceph_pagelist_append(pagelist, method, size);
866+ if (ret)
867+ goto err_pagelist_free;
863868 payload_len += size;
864869
865870 osd_req_op_cls_request_info_pagelist(osd_req, which, pagelist);
866−
867871 op->indata_len = payload_len;
868872 return 0;
873+
874+err_pagelist_free:
875+ ceph_pagelist_release(pagelist);
876+ return ret;
869877 }
870878 EXPORT_SYMBOL(osd_req_op_cls_init);
871879
@@ -877,6 +885,7 @@ int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which, · 5 unmodified lines
877885 opcode, 0);
878886 struct ceph_pagelist *pagelist;
879887 size_t payload_len;
888+ int ret;
880889
881890 BUG_ON(opcode != CEPH_OSD_OP_SETXATTR && opcode != CEPH_OSD_OP_CMPXATTR);
882891
@@ -886,10 +895,14 @@ int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which, · 3 unmodified lines
886895
887896 payload_len = strlen(name);
888897 op->xattr.name_len = payload_len;
889− ceph_pagelist_append(pagelist, name, payload_len);
898+ ret = ceph_pagelist_append(pagelist, name, payload_len);
899+ if (ret)
900+ goto err_pagelist_free;
890901
891902 op->xattr.value_len = size;
892− ceph_pagelist_append(pagelist, value, size);
903+ ret = ceph_pagelist_append(pagelist, value, size);
904+ if (ret)
905+ goto err_pagelist_free;
893906 payload_len += size;
894907
895908 op->xattr.cmp_op = cmp_op;
@@ -898,6 +911,10 @@ int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which, · 2 unmodified lines
898911 ceph_osd_data_pagelist_init(&op->xattr.osd_data, pagelist);
899912 op->indata_len = payload_len;
900913 return 0;
914+
915+err_pagelist_free:
916+ ceph_pagelist_release(pagelist);
917+ return ret;
901918 }
902919 EXPORT_SYMBOL(osd_req_op_xattr_init);
903920
@@ -1488,7 +1505,6 @@ enum calc_target_result { · 584 unmodified lines
14881505
14891506 static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
14901507 struct ceph_osd_request_target *t,
1491− struct ceph_connection *con,
14921508 bool any_change)
14931509 {
14941510 struct ceph_pg_pool_info *pi;
@@ -2272,7 +2288,7 @@ static void __submit_request(struct ceph_osd_request *req, bool wrlocked) · 777 unmodified lines
22722288 dout("%s req %p wrlocked %d\n", __func__, req, wrlocked);
22732289
22742290 again:
2275− ct_res = calc_target(osdc, &req->r_t, NULL, false);
2291+ ct_res = calc_target(osdc, &req->r_t, false);
22762292 if (ct_res == CALC_TARGET_POOL_DNE && !wrlocked)
22772293 goto promote;
22782294
@@ -2476,6 +2492,14 @@ void ceph_osdc_abort_requests(struct ceph_osd_client *osdc, int err) · 197 unmodified lines
24762492 }
24772493 EXPORT_SYMBOL(ceph_osdc_abort_requests);
24782494
2495+void ceph_osdc_clear_abort_err(struct ceph_osd_client *osdc)
2496+{
2497+ down_write(&osdc->lock);
2498+ osdc->abort_err = 0;
2499+ up_write(&osdc->lock);
2500+}
2501+EXPORT_SYMBOL(ceph_osdc_clear_abort_err);
2502+
24792503 static void update_epoch_barrier(struct ceph_osd_client *osdc, u32 eb)
24802504 {
24812505 if (likely(eb > osdc->epoch_barrier)) {
@@ -3087,7 +3111,7 @@ static void linger_submit(struct ceph_osd_linger_request *lreq) · 605 unmodified lines
30873111 lreq->reg_req->r_ops[0].notify.cookie = lreq->linger_id;
30883112 }
30893113
3090− calc_target(osdc, &lreq->t, NULL, false);
3114+ calc_target(osdc, &lreq->t, false);
30913115 osd = lookup_create_osd(osdc, lreq->t.osd, true);
30923116 link_linger(osd, lreq);
30933117
@@ -3704,7 +3728,7 @@ recalc_linger_target(struct ceph_osd_linger_request *lreq) · 610 unmodified lines
37043728 struct ceph_osd_client *osdc = lreq->osdc;
37053729 enum calc_target_result ct_res;
37063730
3707− ct_res = calc_target(osdc, &lreq->t, NULL, true);
3731+ ct_res = calc_target(osdc, &lreq->t, true);
37083732 if (ct_res == CALC_TARGET_NEED_RESEND) {
37093733 struct ceph_osd *osd;
37103734
@@ -3776,8 +3800,7 @@ static void scan_requests(struct ceph_osd *osd, · 65 unmodified lines
37763800 n = rb_next(n); /* unlink_request(), check_pool_dne() */
37773801
37783802 dout("%s req %p tid %llu\n", __func__, req, req->r_tid);
3779− ct_res = calc_target(osdc, &req->r_t, &req->r_osd->o_con,
3780− false);
3803+ ct_res = calc_target(osdc, &req->r_t, false);
37813804 switch (ct_res) {
37823805 case CALC_TARGET_NO_ACTION:
37833806 force_resend_writes = cleared_full ||
@@ -3886,7 +3909,7 @@ static void kick_requests(struct ceph_osd_client *osdc, · 102 unmodified lines
38863909 n = rb_next(n);
38873910
38883911 if (req->r_t.epoch < osdc->osdmap->epoch) {
3889− ct_res = calc_target(osdc, &req->r_t, NULL, false);
3912+ ct_res = calc_target(osdc, &req->r_t, false);
38903913 if (ct_res == CALC_TARGET_POOL_DNE) {
38913914 erase_request(need_resend, req);
38923915 check_pool_dne(req);
@@ -5086,6 +5109,24 @@ out_put_req: · 1193 unmodified lines
50865109 }
50875110 EXPORT_SYMBOL(ceph_osdc_call);
50885111
5112+/*
5113+ * reset all osd connections
5114+ */
5115+void ceph_osdc_reopen_osds(struct ceph_osd_client *osdc)
5116+{
5117+ struct rb_node *n;
5118+
5119+ down_write(&osdc->lock);
5120+ for (n = rb_first(&osdc->osds); n; ) {
5121+ struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
5122+
5123+ n = rb_next(n);
5124+ if (!reopen_osd(osd))
5125+ kick_osd_requests(osd);
5126+ }
5127+ up_write(&osdc->lock);
5128+}
5129+
50895130 /*
50905131 * init, shutdown
50915132 */
net/ceph/osdmap.c+43−26
@@ -973,11 +973,11 @@ void ceph_osdmap_destroy(struct ceph_osdmap *map) · 972 unmodified lines
973973 struct ceph_pg_pool_info, node);
974974 __remove_pg_pool(&map->pg_pools, pi);
975975 }
976− kfree(map->osd_state);
977− kfree(map->osd_weight);
978− kfree(map->osd_addr);
979− kfree(map->osd_primary_affinity);
980− kfree(map->crush_workspace);
976+ kvfree(map->osd_state);
977+ kvfree(map->osd_weight);
978+ kvfree(map->osd_addr);
979+ kvfree(map->osd_primary_affinity);
980+ kvfree(map->crush_workspace);
981981 kfree(map);
982982 }
983983
@@ -986,28 +986,41 @@ void ceph_osdmap_destroy(struct ceph_osdmap *map) · 2 unmodified lines
986986 *
987987 * The new elements are properly initialized.
988988 */
989−static int osdmap_set_max_osd(struct ceph_osdmap *map, int max)
989+static int osdmap_set_max_osd(struct ceph_osdmap *map, u32 max)
990990 {
991991 u32 *state;
992992 u32 *weight;
993993 struct ceph_entity_addr *addr;
994+ u32 to_copy;
994995 int i;
995996
996− state = krealloc(map->osd_state, max*sizeof(*state), GFP_NOFS);
997− if (!state)
998− return -ENOMEM;
999− map->osd_state = state;
997+ dout("%s old %u new %u\n", __func__, map->max_osd, max);
998+ if (max == map->max_osd)
999+ return 0;
10001000
1001− weight = krealloc(map->osd_weight, max*sizeof(*weight), GFP_NOFS);
1002− if (!weight)
1001+ state = ceph_kvmalloc(array_size(max, sizeof(*state)), GFP_NOFS);
1002+ weight = ceph_kvmalloc(array_size(max, sizeof(*weight)), GFP_NOFS);
1003+ addr = ceph_kvmalloc(array_size(max, sizeof(*addr)), GFP_NOFS);
1004+ if (!state || !weight || !addr) {
1005+ kvfree(state);
1006+ kvfree(weight);
1007+ kvfree(addr);
10031008 return -ENOMEM;
1004− map->osd_weight = weight;
1009+ }
10051010
1006− addr = krealloc(map->osd_addr, max*sizeof(*addr), GFP_NOFS);
1007− if (!addr)
1008− return -ENOMEM;
1009− map->osd_addr = addr;
1011+ to_copy = min(map->max_osd, max);
1012+ if (map->osd_state) {
1013+ memcpy(state, map->osd_state, to_copy * sizeof(*state));
1014+ memcpy(weight, map->osd_weight, to_copy * sizeof(*weight));
1015+ memcpy(addr, map->osd_addr, to_copy * sizeof(*addr));
1016+ kvfree(map->osd_state);
1017+ kvfree(map->osd_weight);
1018+ kvfree(map->osd_addr);
1019+ }
10101020
1021+ map->osd_state = state;
1022+ map->osd_weight = weight;
1023+ map->osd_addr = addr;
10111024 for (i = map->max_osd; i < max; i++) {
10121025 map->osd_state[i] = 0;
10131026 map->osd_weight[i] = CEPH_OSD_OUT;
@@ -1017,12 +1030,16 @@ static int osdmap_set_max_osd(struct ceph_osdmap *map, int max) · 3 unmodified lines
10171030 if (map->osd_primary_affinity) {
10181031 u32 *affinity;
10191032
1020− affinity = krealloc(map->osd_primary_affinity,
1021− max*sizeof(*affinity), GFP_NOFS);
1033+ affinity = ceph_kvmalloc(array_size(max, sizeof(*affinity)),
1034+ GFP_NOFS);
10221035 if (!affinity)
10231036 return -ENOMEM;
1024− map->osd_primary_affinity = affinity;
10251037
1038+ memcpy(affinity, map->osd_primary_affinity,
1039+ to_copy * sizeof(*affinity));
1040+ kvfree(map->osd_primary_affinity);
1041+
1042+ map->osd_primary_affinity = affinity;
10261043 for (i = map->max_osd; i < max; i++)
10271044 map->osd_primary_affinity[i] =
10281045 CEPH_OSD_DEFAULT_PRIMARY_AFFINITY;
@@ -1043,7 +1060,7 @@ static int osdmap_set_crush(struct ceph_osdmap *map, struct crush_map *crush) · 14 unmodified lines
10431060
10441061 work_size = crush_work_size(crush, CEPH_PG_MAX_SIZE);
10451062 dout("%s work_size %zu bytes\n", __func__, work_size);
1046− workspace = kmalloc(work_size, GFP_NOIO);
1063+ workspace = ceph_kvmalloc(work_size, GFP_NOIO);
10471064 if (!workspace) {
10481065 crush_destroy(crush);
10491066 return -ENOMEM;
@@ -1052,7 +1069,7 @@ static int osdmap_set_crush(struct ceph_osdmap *map, struct crush_map *crush) · 2 unmodified lines
10521069
10531070 if (map->crush)
10541071 crush_destroy(map->crush);
1055− kfree(map->crush_workspace);
1072+ kvfree(map->crush_workspace);
10561073 map->crush = crush;
10571074 map->crush_workspace = workspace;
10581075 return 0;
@@ -1298,9 +1315,9 @@ static int set_primary_affinity(struct ceph_osdmap *map, int osd, u32 aff) · 239 unmodified lines
12981315 if (!map->osd_primary_affinity) {
12991316 int i;
13001317
1301− map->osd_primary_affinity = kmalloc_array(map->max_osd,
1302− sizeof(u32),
1303− GFP_NOFS);
1318+ map->osd_primary_affinity = ceph_kvmalloc(
1319+ array_size(map->max_osd, sizeof(*map->osd_primary_affinity)),
1320+ GFP_NOFS);
13041321 if (!map->osd_primary_affinity)
13051322 return -ENOMEM;
13061323
@@ -1321,7 +1338,7 @@ static int decode_primary_affinity(void **p, void *end, · 14 unmodified lines
13211338
13221339 ceph_decode_32_safe(p, end, len, e_inval);
13231340 if (len == 0) {
1324− kfree(map->osd_primary_affinity);
1341+ kvfree(map->osd_primary_affinity);
13251342 map->osd_primary_affinity = NULL;
13261343 return 0;
13271344 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t