Commit b5108822 authored by David Howells's avatar David Howells

FS-Cache: Implement data I/O part of netfs API

Implement the data I/O part of the FS-Cache netfs API.  The documentation and
API header file were added in a previous patch.

This patch implements the following functions for the netfs to call:

 (*) fscache_attr_changed().

     Indicate that the object has changed its attributes.  The only attribute
     currently recorded is the file size.  Only pages within the set file size
     will be stored in the cache.

     This operation is submitted for asynchronous processing, and will return
     immediately.  It will return -ENOMEM if an out of memory error is
     encountered, -ENOBUFS if the object is not actually cached, or 0 if the
     operation is successfully queued.

 (*) fscache_read_or_alloc_page().
 (*) fscache_read_or_alloc_pages().

     Request data be fetched from the disk, and allocate internal metadata to
     track the netfs pages and reserve disk space for unknown pages.

     These operations perform semi-asynchronous data reads.  Upon returning
     they will indicate which pages they think can be retrieved from disk, and
     will have set in progress attempts to retrieve those pages.

     These will return, in order of preference, -ENOMEM on memory allocation
     error, -ERESTARTSYS if a signal interrupted proceedings, -ENODATA if one
     or more requested pages are not yet cached, -ENOBUFS if the object is not
     actually cached or if there isn't space for future pages to be cached on
     this object, or 0 if successful.

     In the case of the multipage function, the pages for which reads are set
     in progress will be removed from the list and the page count decreased
     appropriately.

     If any read operations should fail, the completion function will be given
     an error, and will also be passed contextual information to allow the
     netfs to fall back to querying the server for the absent pages.

     For each successful read, the page completion function will also be
     called.

     Any pages subsequently tracked by the cache will have PG_fscache set upon
     them on return.  fscache_uncache_page() must be called for such pages.

     If supplied by the netfs, the mark_pages_cached() cookie op will be
     invoked for any pages now tracked.

 (*) fscache_alloc_page().

     Allocate internal metadata to track a netfs page and reserve disk space.

     This will return -ENOMEM on memory allocation error, -ERESTARTSYS on
     signal, -ENOBUFS if the object isn't cached, or there isn't enough space
     in the cache, or 0 if successful.

     Any pages subsequently tracked by the cache will have PG_fscache set upon
     them on return.  fscache_uncache_page() must be called for such pages.

     If supplied by the netfs, the mark_pages_cached() cookie op will be
     invoked for any pages now tracked.

 (*) fscache_write_page().

     Request data be stored to disk.  This may only be called on pages that
     have been read or alloc'd by the above three functions and have not yet
     been uncached.

     This will return -ENOMEM on memory allocation error, -ERESTARTSYS on
     signal, -ENOBUFS if the object isn't cached, or there isn't immediately
     enough space in the cache, or 0 if successful.

     On a successful return, this operation will have queued the page for
     asynchronous writing to the cache.  The page will be returned with
     PG_fscache_write set until the write completes one way or another.  The
     caller will not be notified if the write fails due to an I/O error.  If
     that happens, the object will become available and all pending writes will
     be aborted.

     Note that the cache may batch up page writes, and so it may take a while
     to get around to writing them out.

     The caller must assume that until PG_fscache_write is cleared the page is
     use by the cache.  Any changes made to the page may be reflected on disk.
     The page may even be under DMA.

 (*) fscache_uncache_page().

     Indicate that the cache should stop tracking a page previously read or
     alloc'd from the cache.  If the page was alloc'd only, but unwritten, it
     will not appear on disk.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarSteve Dickson <steved@redhat.com>
Acked-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
Acked-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Tested-by: default avatarDaire Byrne <Daire.Byrne@framestore.com>
parent 952efe7b
...@@ -9,7 +9,8 @@ fscache-y := \ ...@@ -9,7 +9,8 @@ fscache-y := \
main.o \ main.o \
netfs.o \ netfs.o \
object.o \ object.o \
operation.o operation.o \
page.o
fscache-$(CONFIG_PROC_FS) += proc.o fscache-$(CONFIG_PROC_FS) += proc.o
fscache-$(CONFIG_FSCACHE_STATS) += stats.o fscache-$(CONFIG_FSCACHE_STATS) += stats.o
......
...@@ -229,6 +229,27 @@ static inline void fscache_cookie_put(struct fscache_cookie *cookie) ...@@ -229,6 +229,27 @@ static inline void fscache_cookie_put(struct fscache_cookie *cookie)
__fscache_cookie_put(cookie); __fscache_cookie_put(cookie);
} }
/*
* get an extra reference to a netfs retrieval context
*/
static inline
void *fscache_get_context(struct fscache_cookie *cookie, void *context)
{
if (cookie->def->get_context)
cookie->def->get_context(cookie->netfs_data, context);
return context;
}
/*
* release a reference to a netfs retrieval context
*/
static inline
void fscache_put_context(struct fscache_cookie *cookie, void *context)
{
if (cookie->def->put_context)
cookie->def->put_context(cookie->netfs_data, context);
}
/*****************************************************************************/ /*****************************************************************************/
/* /*
* debug tracing * debug tracing
......
This diff is collapsed.
...@@ -184,6 +184,24 @@ extern struct fscache_cookie *__fscache_acquire_cookie( ...@@ -184,6 +184,24 @@ extern struct fscache_cookie *__fscache_acquire_cookie(
void *); void *);
extern void __fscache_relinquish_cookie(struct fscache_cookie *, int); extern void __fscache_relinquish_cookie(struct fscache_cookie *, int);
extern void __fscache_update_cookie(struct fscache_cookie *); extern void __fscache_update_cookie(struct fscache_cookie *);
extern int __fscache_attr_changed(struct fscache_cookie *);
extern int __fscache_read_or_alloc_page(struct fscache_cookie *,
struct page *,
fscache_rw_complete_t,
void *,
gfp_t);
extern int __fscache_read_or_alloc_pages(struct fscache_cookie *,
struct address_space *,
struct list_head *,
unsigned *,
fscache_rw_complete_t,
void *,
gfp_t);
extern int __fscache_alloc_page(struct fscache_cookie *, struct page *, gfp_t);
extern int __fscache_write_page(struct fscache_cookie *, struct page *, gfp_t);
extern void __fscache_uncache_page(struct fscache_cookie *, struct page *);
extern bool __fscache_check_page_write(struct fscache_cookie *, struct page *);
extern void __fscache_wait_on_page_write(struct fscache_cookie *, struct page *);
/** /**
* fscache_register_netfs - Register a filesystem as desiring caching services * fscache_register_netfs - Register a filesystem as desiring caching services
...@@ -361,7 +379,10 @@ void fscache_unpin_cookie(struct fscache_cookie *cookie) ...@@ -361,7 +379,10 @@ void fscache_unpin_cookie(struct fscache_cookie *cookie)
static inline static inline
int fscache_attr_changed(struct fscache_cookie *cookie) int fscache_attr_changed(struct fscache_cookie *cookie)
{ {
return -ENOBUFS; if (fscache_cookie_valid(cookie))
return __fscache_attr_changed(cookie);
else
return -ENOBUFS;
} }
/** /**
...@@ -418,7 +439,11 @@ int fscache_read_or_alloc_page(struct fscache_cookie *cookie, ...@@ -418,7 +439,11 @@ int fscache_read_or_alloc_page(struct fscache_cookie *cookie,
void *context, void *context,
gfp_t gfp) gfp_t gfp)
{ {
return -ENOBUFS; if (fscache_cookie_valid(cookie))
return __fscache_read_or_alloc_page(cookie, page, end_io_func,
context, gfp);
else
return -ENOBUFS;
} }
/** /**
...@@ -464,7 +489,12 @@ int fscache_read_or_alloc_pages(struct fscache_cookie *cookie, ...@@ -464,7 +489,12 @@ int fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
void *context, void *context,
gfp_t gfp) gfp_t gfp)
{ {
return -ENOBUFS; if (fscache_cookie_valid(cookie))
return __fscache_read_or_alloc_pages(cookie, mapping, pages,
nr_pages, end_io_func,
context, gfp);
else
return -ENOBUFS;
} }
/** /**
...@@ -490,7 +520,10 @@ int fscache_alloc_page(struct fscache_cookie *cookie, ...@@ -490,7 +520,10 @@ int fscache_alloc_page(struct fscache_cookie *cookie,
struct page *page, struct page *page,
gfp_t gfp) gfp_t gfp)
{ {
return -ENOBUFS; if (fscache_cookie_valid(cookie))
return __fscache_alloc_page(cookie, page, gfp);
else
return -ENOBUFS;
} }
/** /**
...@@ -516,7 +549,10 @@ int fscache_write_page(struct fscache_cookie *cookie, ...@@ -516,7 +549,10 @@ int fscache_write_page(struct fscache_cookie *cookie,
struct page *page, struct page *page,
gfp_t gfp) gfp_t gfp)
{ {
return -ENOBUFS; if (fscache_cookie_valid(cookie))
return __fscache_write_page(cookie, page, gfp);
else
return -ENOBUFS;
} }
/** /**
...@@ -537,6 +573,8 @@ static inline ...@@ -537,6 +573,8 @@ static inline
void fscache_uncache_page(struct fscache_cookie *cookie, void fscache_uncache_page(struct fscache_cookie *cookie,
struct page *page) struct page *page)
{ {
if (fscache_cookie_valid(cookie))
__fscache_uncache_page(cookie, page);
} }
/** /**
...@@ -553,6 +591,8 @@ static inline ...@@ -553,6 +591,8 @@ static inline
bool fscache_check_page_write(struct fscache_cookie *cookie, bool fscache_check_page_write(struct fscache_cookie *cookie,
struct page *page) struct page *page)
{ {
if (fscache_cookie_valid(cookie))
return __fscache_check_page_write(cookie, page);
return false; return false;
} }
...@@ -571,6 +611,8 @@ static inline ...@@ -571,6 +611,8 @@ static inline
void fscache_wait_on_page_write(struct fscache_cookie *cookie, void fscache_wait_on_page_write(struct fscache_cookie *cookie,
struct page *page) struct page *page)
{ {
if (fscache_cookie_valid(cookie))
__fscache_wait_on_page_write(cookie, page);
} }
#endif /* _LINUX_FSCACHE_H */ #endif /* _LINUX_FSCACHE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment