Merge tag 'ceph-for-5.15-rc1' of git://github.com/ceph/ceph-client
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 8 Sep 2021 22:50:32 +0000 (15:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 8 Sep 2021 22:50:32 +0000 (15:50 -0700)
Pull ceph updates from Ilya Dryomov:

 - a set of patches to address fsync stalls caused by depending on
   periodic rather than triggered MDS journal flushes in some cases
   (Xiubo Li)

 - a fix for mtime effectively not getting updated in case of competing
   writers (Jeff Layton)

 - a couple of fixes for inode reference leaks and various WARNs after
   "umount -f" (Xiubo Li)

 - a new ceph.auth_mds extended attribute (Jeff Layton)

 - a smattering of fixups and cleanups from Jeff, Xiubo and Colin.

* tag 'ceph-for-5.15-rc1' of git://github.com/ceph/ceph-client:
  ceph: fix dereference of null pointer cf
  ceph: drop the mdsc_get_session/put_session dout messages
  ceph: lockdep annotations for try_nonblocking_invalidate
  ceph: don't WARN if we're forcibly removing the session caps
  ceph: don't WARN if we're force umounting
  ceph: remove the capsnaps when removing caps
  ceph: request Fw caps before updating the mtime in ceph_write_iter
  ceph: reconnect to the export targets on new mdsmaps
  ceph: print more information when we can't find snaprealm
  ceph: add ceph_change_snap_realm() helper
  ceph: remove redundant initializations from mdsc and session
  ceph: cancel delayed work instead of flushing on mdsc teardown
  ceph: add a new vxattr to return auth mds for an inode
  ceph: remove some defunct forward declarations
  ceph: flush the mdlog before waiting on unsafe reqs
  ceph: flush mdlog before umounting
  ceph: make iterate_sessions a global symbol
  ceph: make ceph_create_session_msg a global symbol
  ceph: fix comment about short copies in ceph_write_end
  ceph: fix memory leak on decode error in ceph_handle_caps

1  2 
fs/ceph/addr.c
fs/ceph/file.c
fs/ceph/super.h

diff --combined fs/ceph/addr.c
@@@ -1281,8 -1281,8 +1281,8 @@@ static int ceph_write_end(struct file *
        dout("write_end file %p inode %p page %p %d~%d (%d)\n", file,
             inode, page, (int)pos, (int)copied, (int)len);
  
-       /* zero the stale part of the page if we did a short copy */
        if (!PageUptodate(page)) {
+               /* just return that nothing was copied on a short copy */
                if (copied < len) {
                        copied = 0;
                        goto out;
@@@ -1395,11 -1395,9 +1395,11 @@@ static vm_fault_t ceph_filemap_fault(st
                ret = VM_FAULT_SIGBUS;
        } else {
                struct address_space *mapping = inode->i_mapping;
 -              struct page *page = find_or_create_page(mapping, 0,
 -                                              mapping_gfp_constraint(mapping,
 -                                              ~__GFP_FS));
 +              struct page *page;
 +
 +              filemap_invalidate_lock_shared(mapping);
 +              page = find_or_create_page(mapping, 0,
 +                              mapping_gfp_constraint(mapping, ~__GFP_FS));
                if (!page) {
                        ret = VM_FAULT_OOM;
                        goto out_inline;
                vmf->page = page;
                ret = VM_FAULT_MAJOR | VM_FAULT_LOCKED;
  out_inline:
 +              filemap_invalidate_unlock_shared(mapping);
                dout("filemap_fault %p %llu read inline data ret %x\n",
                     inode, off, ret);
        }
diff --combined fs/ceph/file.c
@@@ -1722,32 -1722,26 +1722,26 @@@ retry_snap
                goto out;
        }
  
-       err = file_remove_privs(file);
-       if (err)
+       down_read(&osdc->lock);
+       map_flags = osdc->osdmap->flags;
+       pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id);
+       up_read(&osdc->lock);
+       if ((map_flags & CEPH_OSDMAP_FULL) ||
+           (pool_flags & CEPH_POOL_FLAG_FULL)) {
+               err = -ENOSPC;
                goto out;
+       }
  
-       err = file_update_time(file);
+       err = file_remove_privs(file);
        if (err)
                goto out;
  
-       inode_inc_iversion_raw(inode);
        if (ci->i_inline_version != CEPH_INLINE_NONE) {
                err = ceph_uninline_data(file, NULL);
                if (err < 0)
                        goto out;
        }
  
-       down_read(&osdc->lock);
-       map_flags = osdc->osdmap->flags;
-       pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id);
-       up_read(&osdc->lock);
-       if ((map_flags & CEPH_OSDMAP_FULL) ||
-           (pool_flags & CEPH_POOL_FLAG_FULL)) {
-               err = -ENOSPC;
-               goto out;
-       }
        dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n",
             inode, ceph_vinop(inode), pos, count, i_size_read(inode));
        if (fi->fmode & CEPH_FILE_MODE_LAZY)
        if (err < 0)
                goto out;
  
+       err = file_update_time(file);
+       if (err)
+               goto out_caps;
+       inode_inc_iversion_raw(inode);
        dout("aio_write %p %llx.%llx %llu~%zd got cap refs on %s\n",
             inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
  
        }
  
        goto out_unlocked;
+ out_caps:
+       ceph_put_cap_refs(ci, got);
  out:
        if (direct_lock)
                ceph_end_io_direct(inode);
@@@ -2088,7 -2090,6 +2090,7 @@@ static long ceph_fallocate(struct file 
        if (ret < 0)
                goto unlock;
  
 +      filemap_invalidate_lock(inode->i_mapping);
        ceph_zero_pagecache_range(inode, offset, length);
        ret = ceph_zero_objects(inode, offset, length);
  
                if (dirty)
                        __mark_inode_dirty(inode, dirty);
        }
 +      filemap_invalidate_unlock(inode->i_mapping);
  
        ceph_put_cap_refs(ci, got);
  unlock:
diff --combined fs/ceph/super.h
@@@ -418,7 -418,6 +418,6 @@@ struct ceph_inode_info 
                struct ceph_snap_realm *i_snap_realm; /* snap realm (if caps) */
                struct ceph_snapid_map *i_snapid_map; /* snapid -> dev_t */
        };
-       int i_snap_realm_counter; /* snap realm (if caps) */
        struct list_head i_snap_realm_item;
        struct list_head i_snap_flush_item;
        struct timespec64 i_btime;
@@@ -929,6 -928,7 +928,7 @@@ extern void ceph_put_snap_realm(struct 
  extern int ceph_update_snap_trace(struct ceph_mds_client *m,
                                  void *p, void *e, bool deletion,
                                  struct ceph_snap_realm **realm_ret);
+ void ceph_change_snap_realm(struct inode *inode, struct ceph_snap_realm *realm);
  extern void ceph_handle_snap(struct ceph_mds_client *mdsc,
                             struct ceph_mds_session *session,
                             struct ceph_msg *msg);
@@@ -1088,7 -1088,7 +1088,7 @@@ void ceph_release_acl_sec_ctx(struct ce
  /* acl.c */
  #ifdef CONFIG_CEPH_FS_POSIX_ACL
  
 -struct posix_acl *ceph_get_acl(struct inode *, int);
 +struct posix_acl *ceph_get_acl(struct inode *, int, bool);
  int ceph_set_acl(struct user_namespace *mnt_userns,
                 struct inode *inode, struct posix_acl *acl, int type);
  int ceph_pre_init_acls(struct inode *dir, umode_t *mode,
@@@ -1138,6 -1138,7 +1138,7 @@@ extern void ceph_add_cap(struct inode *
                         unsigned cap, unsigned seq, u64 realmino, int flags,
                         struct ceph_cap **new_cap);
  extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
+ extern void ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
  extern void __ceph_remove_caps(struct ceph_inode_info *ci);
  extern void ceph_put_cap(struct ceph_mds_client *mdsc,
                         struct ceph_cap *cap);
@@@ -1163,6 -1164,12 +1164,12 @@@ extern void ceph_put_cap_refs_no_check_
                                            int had);
  extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
                                       struct ceph_snap_context *snapc);
+ extern void __ceph_remove_capsnap(struct inode *inode,
+                                 struct ceph_cap_snap *capsnap,
+                                 bool *wake_ci, bool *wake_mdsc);
+ extern void ceph_remove_capsnap(struct inode *inode,
+                               struct ceph_cap_snap *capsnap,
+                               bool *wake_ci, bool *wake_mdsc);
  extern void ceph_flush_snaps(struct ceph_inode_info *ci,
                             struct ceph_mds_session **psession);
  extern bool __ceph_should_report_size(struct ceph_inode_info *ci);