Commit 7ac86b3d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull ceph updates from Ilya Dryomov:
 "Notable items here are

   - a series to take advantage of David Howells' netfs helper library
     from Jeff

   - three new filesystem client metrics from Xiubo

   - ceph.dir.rsnaps vxattr from Yanhu

   - two auth-related fixes from myself, marked for stable.

  Interspersed is a smattering of assorted fixes and cleanups across the
  filesystem"

* tag 'ceph-for-5.13-rc1' of git://github.com/ceph/ceph-client: (24 commits)
  libceph: allow addrvecs with a single NONE/blank address
  libceph: don't set global_id until we get an auth ticket
  libceph: bump CephXAuthenticate encoding version
  ceph: don't allow access to MDS-private inodes
  ceph: fix up some bare fetches of i_size
  ceph: convert some PAGE_SIZE invocations to thp_size()
  ceph: support getting ceph.dir.rsnaps vxattr
  ceph: drop pinned_page parameter from ceph_get_caps
  ceph: fix inode leak on getattr error in __fh_to_dentry
  ceph: only check pool permissions for regular files
  ceph: send opened files/pinned caps/opened inodes metrics to MDS daemon
  ceph: avoid counting the same request twice or more
  ceph: rename the metric helpers
  ceph: fix kerneldoc copypasta over ceph_start_io_direct
  ceph: use attach/detach_page_private for tracking snap context
  ceph: don't use d_add in ceph_handle_snapdir
  ceph: don't clobber i_snap_caps on non-I_NEW inode
  ceph: fix fall-through warnings for Clang
  ceph: convert ceph_readpages to ceph_readahead
  ceph: convert ceph_write_begin to netfs_write_begin
  ...
parents 682a8e2b 3f1c6f21
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ config CEPH_FS
	select LIBCRC32C
	select CRYPTO_AES
	select CRYPTO
	select NETFS_SUPPORT
	default n
	help
	  Choose Y or M here to include support for mounting the
+254 −372

File changed.

Preview size limit exceeded, changes collapsed.

+0 −125
Original line number Diff line number Diff line
@@ -173,7 +173,6 @@ void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)

	ci->fscache = NULL;

	fscache_uncache_all_inode_pages(cookie, &ci->vfs_inode);
	fscache_relinquish_cookie(cookie, &ci->i_vino, false);
}

@@ -194,7 +193,6 @@ void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp)
		dout("fscache_file_set_cookie %p %p disabling cache\n",
		     inode, filp);
		fscache_disable_cookie(ci->fscache, &ci->i_vino, false);
		fscache_uncache_all_inode_pages(ci->fscache, inode);
	} else {
		fscache_enable_cookie(ci->fscache, &ci->i_vino, i_size_read(inode),
				      ceph_fscache_can_enable, inode);
@@ -205,108 +203,6 @@ void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp)
	}
}

static void ceph_readpage_from_fscache_complete(struct page *page, void *data, int error)
{
	if (!error)
		SetPageUptodate(page);

	unlock_page(page);
}

static inline bool cache_valid(struct ceph_inode_info *ci)
{
	return ci->i_fscache_gen == ci->i_rdcache_gen;
}


/* Atempt to read from the fscache,
 *
 * This function is called from the readpage_nounlock context. DO NOT attempt to
 * unlock the page here (or in the callback).
 */
int ceph_readpage_from_fscache(struct inode *inode, struct page *page)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	int ret;

	if (!cache_valid(ci))
		return -ENOBUFS;

	ret = fscache_read_or_alloc_page(ci->fscache, page,
					 ceph_readpage_from_fscache_complete, NULL,
					 GFP_KERNEL);

	switch (ret) {
		case 0: /* Page found */
			dout("page read submitted\n");
			return 0;
		case -ENOBUFS: /* Pages were not found, and can't be */
		case -ENODATA: /* Pages were not found */
			dout("page/inode not in cache\n");
			return ret;
		default:
			dout("%s: unknown error ret = %i\n", __func__, ret);
			return ret;
	}
}

int ceph_readpages_from_fscache(struct inode *inode,
				  struct address_space *mapping,
				  struct list_head *pages,
				  unsigned *nr_pages)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	int ret;

	if (!cache_valid(ci))
		return -ENOBUFS;

	ret = fscache_read_or_alloc_pages(ci->fscache, mapping, pages, nr_pages,
					  ceph_readpage_from_fscache_complete,
					  NULL, mapping_gfp_mask(mapping));

	switch (ret) {
		case 0: /* All pages found */
			dout("all-page read submitted\n");
			return 0;
		case -ENOBUFS: /* Some pages were not found, and can't be */
		case -ENODATA: /* some pages were not found */
			dout("page/inode not in cache\n");
			return ret;
		default:
			dout("%s: unknown error ret = %i\n", __func__, ret);
			return ret;
	}
}

void ceph_readpage_to_fscache(struct inode *inode, struct page *page)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	int ret;

	if (!PageFsCache(page))
		return;

	if (!cache_valid(ci))
		return;

	ret = fscache_write_page(ci->fscache, page, i_size_read(inode),
				 GFP_KERNEL);
	if (ret)
		 fscache_uncache_page(ci->fscache, page);
}

void ceph_invalidate_fscache_page(struct inode* inode, struct page *page)
{
	struct ceph_inode_info *ci = ceph_inode(inode);

	if (!PageFsCache(page))
		return;

	fscache_wait_on_page_write(ci->fscache, page);
	fscache_uncache_page(ci->fscache, page);
}

void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
{
	if (fscache_cookie_valid(fsc->fscache)) {
@@ -329,24 +225,3 @@ void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
	}
	fsc->fscache = NULL;
}

/*
 * caller should hold CEPH_CAP_FILE_{RD,CACHE}
 */
void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci)
{
	if (cache_valid(ci))
		return;

	/* resue i_truncate_mutex. There should be no pending
	 * truncate while the caller holds CEPH_CAP_FILE_RD */
	mutex_lock(&ci->i_truncate_mutex);
	if (!cache_valid(ci)) {
		if (fscache_check_consistency(ci->fscache, &ci->i_vino))
			fscache_invalidate(ci->fscache);
		spin_lock(&ci->i_ceph_lock);
		ci->i_fscache_gen = ci->i_rdcache_gen;
		spin_unlock(&ci->i_ceph_lock);
	}
	mutex_unlock(&ci->i_truncate_mutex);
}
+24 −77
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
#ifndef _CEPH_CACHE_H
#define _CEPH_CACHE_H

#include <linux/netfs.h>

#ifdef CONFIG_CEPH_FSCACHE

extern struct fscache_netfs ceph_cache_netfs;
@@ -29,54 +31,37 @@ int ceph_readpages_from_fscache(struct inode *inode,
				struct address_space *mapping,
				struct list_head *pages,
				unsigned *nr_pages);
void ceph_readpage_to_fscache(struct inode *inode, struct page *page);
void ceph_invalidate_fscache_page(struct inode* inode, struct page *page);

static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci)
{
	ci->fscache = NULL;
	ci->i_fscache_gen = 0;
}

static inline void ceph_fscache_invalidate(struct inode *inode)
static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info *ci)
{
	fscache_invalidate(ceph_inode(inode)->fscache);
	return ci->fscache;
}

static inline void ceph_fscache_uncache_page(struct inode *inode,
					     struct page *page)
static inline void ceph_fscache_invalidate(struct inode *inode)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	return fscache_uncache_page(ci->fscache, page);
	fscache_invalidate(ceph_inode(inode)->fscache);
}

static inline int ceph_release_fscache_page(struct page *page, gfp_t gfp)
static inline bool ceph_is_cache_enabled(struct inode *inode)
{
	struct inode* inode = page->mapping->host;
	struct ceph_inode_info *ci = ceph_inode(inode);
	return fscache_maybe_release_page(ci->fscache, page, gfp);
}
	struct fscache_cookie *cookie = ceph_fscache_cookie(ceph_inode(inode));

static inline void ceph_fscache_readpage_cancel(struct inode *inode,
						struct page *page)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	if (fscache_cookie_valid(ci->fscache) && PageFsCache(page))
		__fscache_uncache_page(ci->fscache, page);
	if (!cookie)
		return false;
	return fscache_cookie_enabled(cookie);
}

static inline void ceph_fscache_readpages_cancel(struct inode *inode,
						 struct list_head *pages)
static inline int ceph_begin_cache_operation(struct netfs_read_request *rreq)
{
	struct ceph_inode_info *ci = ceph_inode(inode);
	return fscache_readpages_cancel(ci->fscache, pages);
}
	struct fscache_cookie *cookie = ceph_fscache_cookie(ceph_inode(rreq->inode));

static inline void ceph_disable_fscache_readpage(struct ceph_inode_info *ci)
{
	ci->i_fscache_gen = ci->i_rdcache_gen - 1;
	return fscache_begin_read_operation(rreq, cookie);
}

#else

static inline int ceph_fscache_register(void)
@@ -102,6 +87,11 @@ static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci)
{
}

static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info *ci)
{
	return NULL;
}

static inline void ceph_fscache_register_inode_cookie(struct inode *inode)
{
}
@@ -115,62 +105,19 @@ static inline void ceph_fscache_file_set_cookie(struct inode *inode,
{
}

static inline void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci)
{
}

static inline void ceph_fscache_uncache_page(struct inode *inode,
					     struct page *pages)
{
}

static inline int ceph_readpage_from_fscache(struct inode* inode,
					     struct page *page)
{
	return -ENOBUFS;
}

static inline int ceph_readpages_from_fscache(struct inode *inode,
					      struct address_space *mapping,
					      struct list_head *pages,
					      unsigned *nr_pages)
{
	return -ENOBUFS;
}

static inline void ceph_readpage_to_fscache(struct inode *inode,
					    struct page *page)
{
}

static inline void ceph_fscache_invalidate(struct inode *inode)
{
}

static inline void ceph_invalidate_fscache_page(struct inode *inode,
						struct page *page)
{
}

static inline int ceph_release_fscache_page(struct page *page, gfp_t gfp)
{
	return 1;
}

static inline void ceph_fscache_readpage_cancel(struct inode *inode,
						struct page *page)
static inline bool ceph_is_cache_enabled(struct inode *inode)
{
	return false;
}

static inline void ceph_fscache_readpages_cancel(struct inode *inode,
						 struct list_head *pages)
{
}

static inline void ceph_disable_fscache_readpage(struct ceph_inode_info *ci)
static inline int ceph_begin_cache_operation(struct netfs_read_request *rreq)
{
	return -ENOBUFS;
}

#endif

#endif
#endif /* _CEPH_CACHE_H */
+9 −18
Original line number Diff line number Diff line
@@ -1390,7 +1390,7 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
	arg->flush_tid = flush_tid;
	arg->oldest_flush_tid = oldest_flush_tid;

	arg->size = inode->i_size;
	arg->size = i_size_read(inode);
	ci->i_reported_size = arg->size;
	arg->max_size = ci->i_wanted_max_size;
	if (cap == ci->i_auth_cap) {
@@ -1867,6 +1867,7 @@ static int try_nonblocking_invalidate(struct inode *inode)
	u32 invalidating_gen = ci->i_rdcache_gen;

	spin_unlock(&ci->i_ceph_lock);
	ceph_fscache_invalidate(inode);
	invalidate_mapping_pages(&inode->i_data, 0, -1);
	spin_lock(&ci->i_ceph_lock);

@@ -1884,7 +1885,7 @@ static int try_nonblocking_invalidate(struct inode *inode)

bool __ceph_should_report_size(struct ceph_inode_info *ci)
{
	loff_t size = ci->vfs_inode.i_size;
	loff_t size = i_size_read(&ci->vfs_inode);
	/* mds will adjust max size according to the reported size */
	if (ci->i_flushing_caps & CEPH_CAP_FILE_WR)
		return false;
@@ -2730,10 +2731,6 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
				*got = need | want;
			else
				*got = need;
			if (S_ISREG(inode->i_mode) &&
			    (need & CEPH_CAP_FILE_RD) &&
			    !(*got & CEPH_CAP_FILE_CACHE))
				ceph_disable_fscache_readpage(ci);
			ceph_take_cap_refs(ci, *got, true);
			ret = 1;
		}
@@ -2858,8 +2855,7 @@ int ceph_try_get_caps(struct inode *inode, int need, int want,
 * due to a small max_size, make sure we check_max_size (and possibly
 * ask the mds) so we don't get hung up indefinitely.
 */
int ceph_get_caps(struct file *filp, int need, int want,
		  loff_t endoff, int *got, struct page **pinned_page)
int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff, int *got)
{
	struct ceph_file_info *fi = filp->private_data;
	struct inode *inode = file_inode(filp);
@@ -2957,11 +2953,11 @@ int ceph_get_caps(struct file *filp, int need, int want,
			struct page *page =
				find_get_page(inode->i_mapping, 0);
			if (page) {
				if (PageUptodate(page)) {
					*pinned_page = page;
					break;
				}
				bool uptodate = PageUptodate(page);

				put_page(page);
				if (uptodate)
					break;
			}
			/*
			 * drop cap refs first because getattr while
@@ -2983,11 +2979,6 @@ int ceph_get_caps(struct file *filp, int need, int want,
		}
		break;
	}

	if (S_ISREG(ci->vfs_inode.i_mode) &&
	    (_got & CEPH_CAP_FILE_RD) && (_got & CEPH_CAP_FILE_CACHE))
		ceph_fscache_revalidate_cookie(ci);

	*got = _got;
	return 0;
}
@@ -3308,7 +3299,7 @@ static void handle_cap_grant(struct inode *inode,
	dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
	     inode, cap, session->s_mds, seq, ceph_cap_string(newcaps));
	dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
		inode->i_size);
		i_size_read(inode));


	/*
Loading