Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54afa990 authored by David Howells's avatar David Howells Committed by Steve French
Browse files

CIFS: FS-Cache: Uncache unread pages in cifs_readpages() before freeing them



In cifs_readpages(), we may decide we don't want to read a page after all -
but the page may already have passed through fscache_read_or_alloc_pages() and
thus have marks and reservations set.  Thus we have to call
fscache_readpages_cancel() or fscache_uncache_page() on the pages we're
returning to clear the marks.

NFS, AFS and 9P should be unaffected by this as they call read_cache_pages()
which does the cleanup for you.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 62d228b8
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -3254,6 +3254,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
	/*
	/*
	 * Reads as many pages as possible from fscache. Returns -ENOBUFS
	 * Reads as many pages as possible from fscache. Returns -ENOBUFS
	 * immediately if the cookie is negative
	 * immediately if the cookie is negative
	 *
	 * After this point, every page in the list might have PG_fscache set,
	 * so we will need to clean that up off of every page we don't use.
	 */
	 */
	rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
	rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
					 &num_pages);
					 &num_pages);
@@ -3376,6 +3379,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
		kref_put(&rdata->refcount, cifs_readdata_release);
		kref_put(&rdata->refcount, cifs_readdata_release);
	}
	}


	/* Any pages that have been shown to fscache but didn't get added to
	 * the pagecache must be uncached before they get returned to the
	 * allocator.
	 */
	cifs_fscache_readpages_cancel(mapping->host, page_list);
	return rc;
	return rc;
}
}


+7 −0
Original line number Original line Diff line number Diff line
@@ -223,6 +223,13 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
		fscache_uncache_page(CIFS_I(inode)->fscache, page);
		fscache_uncache_page(CIFS_I(inode)->fscache, page);
}
}


void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages)
{
	cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n",
		 __func__, CIFS_I(inode)->fscache, inode);
	fscache_readpages_cancel(CIFS_I(inode)->fscache, pages);
}

void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
{
{
	struct cifsInodeInfo *cifsi = CIFS_I(inode);
	struct cifsInodeInfo *cifsi = CIFS_I(inode);
+13 −0
Original line number Original line Diff line number Diff line
@@ -54,6 +54,7 @@ extern int __cifs_readpages_from_fscache(struct inode *,
					 struct address_space *,
					 struct address_space *,
					 struct list_head *,
					 struct list_head *,
					 unsigned *);
					 unsigned *);
extern void __cifs_fscache_readpages_cancel(struct inode *, struct list_head *);


extern void __cifs_readpage_to_fscache(struct inode *, struct page *);
extern void __cifs_readpage_to_fscache(struct inode *, struct page *);


@@ -91,6 +92,13 @@ static inline void cifs_readpage_to_fscache(struct inode *inode,
		__cifs_readpage_to_fscache(inode, page);
		__cifs_readpage_to_fscache(inode, page);
}
}


static inline void cifs_fscache_readpages_cancel(struct inode *inode,
						 struct list_head *pages)
{
	if (CIFS_I(inode)->fscache)
		return __cifs_fscache_readpages_cancel(inode, pages);
}

#else /* CONFIG_CIFS_FSCACHE */
#else /* CONFIG_CIFS_FSCACHE */
static inline int cifs_fscache_register(void) { return 0; }
static inline int cifs_fscache_register(void) { return 0; }
static inline void cifs_fscache_unregister(void) {}
static inline void cifs_fscache_unregister(void) {}
@@ -131,6 +139,11 @@ static inline int cifs_readpages_from_fscache(struct inode *inode,
static inline void cifs_readpage_to_fscache(struct inode *inode,
static inline void cifs_readpage_to_fscache(struct inode *inode,
			struct page *page) {}
			struct page *page) {}


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

#endif /* CONFIG_CIFS_FSCACHE */
#endif /* CONFIG_CIFS_FSCACHE */


#endif /* _CIFS_FSCACHE_H */
#endif /* _CIFS_FSCACHE_H */