Commit 1ce9d792 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ceph-for-5.19-rc7' of https://github.com/ceph/ceph-client

Pull ceph fix from Ilya Dryomov:
 "A folio locking fixup that Xiubo and David cooperated on, marked for
  stable. Most of it is in netfs but I picked it up into ceph tree on
  agreement with David"

* tag 'ceph-for-5.19-rc7' of https://github.com/ceph/ceph-client:
  netfs: do not unlock and put the folio twice
parents 8006112d fac47b43
...@@ -301,7 +301,7 @@ through which it can issue requests and negotiate:: ...@@ -301,7 +301,7 @@ through which it can issue requests and negotiate::
void (*issue_read)(struct netfs_io_subrequest *subreq); void (*issue_read)(struct netfs_io_subrequest *subreq);
bool (*is_still_valid)(struct netfs_io_request *rreq); bool (*is_still_valid)(struct netfs_io_request *rreq);
int (*check_write_begin)(struct file *file, loff_t pos, unsigned len, int (*check_write_begin)(struct file *file, loff_t pos, unsigned len,
struct folio *folio, void **_fsdata); struct folio **foliop, void **_fsdata);
void (*done)(struct netfs_io_request *rreq); void (*done)(struct netfs_io_request *rreq);
}; };
...@@ -381,8 +381,10 @@ The operations are as follows: ...@@ -381,8 +381,10 @@ The operations are as follows:
allocated/grabbed the folio to be modified to allow the filesystem to flush allocated/grabbed the folio to be modified to allow the filesystem to flush
conflicting state before allowing it to be modified. conflicting state before allowing it to be modified.
It should return 0 if everything is now fine, -EAGAIN if the folio should be It may unlock and discard the folio it was given and set the caller's folio
regrabbed and any other error code to abort the operation. pointer to NULL. It should return 0 if everything is now fine (``*foliop``
left set) or the op should be retried (``*foliop`` cleared) and any other
error code to abort the operation.
* ``done`` * ``done``
......
...@@ -375,7 +375,7 @@ static int afs_begin_cache_operation(struct netfs_io_request *rreq) ...@@ -375,7 +375,7 @@ static int afs_begin_cache_operation(struct netfs_io_request *rreq)
} }
static int afs_check_write_begin(struct file *file, loff_t pos, unsigned len, static int afs_check_write_begin(struct file *file, loff_t pos, unsigned len,
struct folio *folio, void **_fsdata) struct folio **foliop, void **_fsdata)
{ {
struct afs_vnode *vnode = AFS_FS_I(file_inode(file)); struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
(CONGESTION_ON_THRESH(congestion_kb) >> 2)) (CONGESTION_ON_THRESH(congestion_kb) >> 2))
static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned int len, static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned int len,
struct folio *folio, void **_fsdata); struct folio **foliop, void **_fsdata);
static inline struct ceph_snap_context *page_snap_context(struct page *page) static inline struct ceph_snap_context *page_snap_context(struct page *page)
{ {
...@@ -1288,18 +1288,19 @@ ceph_find_incompatible(struct page *page) ...@@ -1288,18 +1288,19 @@ ceph_find_incompatible(struct page *page)
} }
static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned int len, static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned int len,
struct folio *folio, void **_fsdata) struct folio **foliop, void **_fsdata)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_snap_context *snapc; struct ceph_snap_context *snapc;
snapc = ceph_find_incompatible(folio_page(folio, 0)); snapc = ceph_find_incompatible(folio_page(*foliop, 0));
if (snapc) { if (snapc) {
int r; int r;
folio_unlock(folio); folio_unlock(*foliop);
folio_put(folio); folio_put(*foliop);
*foliop = NULL;
if (IS_ERR(snapc)) if (IS_ERR(snapc))
return PTR_ERR(snapc); return PTR_ERR(snapc);
......
...@@ -319,8 +319,9 @@ static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t len, ...@@ -319,8 +319,9 @@ static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t len,
* conflicting writes once the folio is grabbed and locked. It is passed a * conflicting writes once the folio is grabbed and locked. It is passed a
* pointer to the fsdata cookie that gets returned to the VM to be passed to * pointer to the fsdata cookie that gets returned to the VM to be passed to
* write_end. It is permitted to sleep. It should return 0 if the request * write_end. It is permitted to sleep. It should return 0 if the request
* should go ahead; unlock the folio and return -EAGAIN to cause the folio to * should go ahead or it may return an error. It may also unlock and put the
* be regot; or return an error. * folio, provided it sets ``*foliop`` to NULL, in which case a return of 0
* will cause the folio to be re-got and the process to be retried.
* *
* The calling netfs must initialise a netfs context contiguous to the vfs * The calling netfs must initialise a netfs context contiguous to the vfs
* inode before calling this. * inode before calling this.
...@@ -348,13 +349,13 @@ int netfs_write_begin(struct netfs_inode *ctx, ...@@ -348,13 +349,13 @@ int netfs_write_begin(struct netfs_inode *ctx,
if (ctx->ops->check_write_begin) { if (ctx->ops->check_write_begin) {
/* Allow the netfs (eg. ceph) to flush conflicts. */ /* Allow the netfs (eg. ceph) to flush conflicts. */
ret = ctx->ops->check_write_begin(file, pos, len, folio, _fsdata); ret = ctx->ops->check_write_begin(file, pos, len, &folio, _fsdata);
if (ret < 0) { if (ret < 0) {
trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin); trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin);
if (ret == -EAGAIN)
goto retry;
goto error; goto error;
} }
if (!folio)
goto retry;
} }
if (folio_test_uptodate(folio)) if (folio_test_uptodate(folio))
...@@ -416,8 +417,10 @@ int netfs_write_begin(struct netfs_inode *ctx, ...@@ -416,8 +417,10 @@ int netfs_write_begin(struct netfs_inode *ctx,
error_put: error_put:
netfs_put_request(rreq, false, netfs_rreq_trace_put_failed); netfs_put_request(rreq, false, netfs_rreq_trace_put_failed);
error: error:
folio_unlock(folio); if (folio) {
folio_put(folio); folio_unlock(folio);
folio_put(folio);
}
_leave(" = %d", ret); _leave(" = %d", ret);
return ret; return ret;
} }
......
...@@ -214,7 +214,7 @@ struct netfs_request_ops { ...@@ -214,7 +214,7 @@ struct netfs_request_ops {
void (*issue_read)(struct netfs_io_subrequest *subreq); void (*issue_read)(struct netfs_io_subrequest *subreq);
bool (*is_still_valid)(struct netfs_io_request *rreq); bool (*is_still_valid)(struct netfs_io_request *rreq);
int (*check_write_begin)(struct file *file, loff_t pos, unsigned len, int (*check_write_begin)(struct file *file, loff_t pos, unsigned len,
struct folio *folio, void **_fsdata); struct folio **foliop, void **_fsdata);
void (*done)(struct netfs_io_request *rreq); void (*done)(struct netfs_io_request *rreq);
}; };
......
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