Change the request initialisation function to return an error code so that the network filesystem can return a failure (ENOMEM, for example). This will also allow ceph to abort a ->readahead() op if the server refuses to give it a cap allowing local caching from within the netfslib framework (errors aren't passed back through ->readahead(), so returning, say, -ENOBUFS will cause the op to be aborted). Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> cc: linux-cachefs@redhat.com
Unified · Split
| @@ -56,12 +56,13 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq) · 55 unmodified lines | |||
| 56 | * @rreq: The read request | 56 | * @rreq: The read request |
| 57 | * @file: The file being read from | 57 | * @file: The file being read from |
| 58 | */ | 58 | */ |
| 59 | static void v9fs_init_request(struct netfs_io_request *rreq, struct file *file) | 59 | static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file) |
| 60 | { | 60 | { |
| 61 | struct p9_fid *fid = file->private_data; | 61 | struct p9_fid *fid = file->private_data; |
| 62 | 62 | ||
| 63 | refcount_inc(&fid->count); | 63 | refcount_inc(&fid->count); |
| 64 | rreq->netfs_priv = fid; | 64 | rreq->netfs_priv = fid; |
| 65 | return 0; | ||
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | /** | 68 | /** |
| @@ -359,9 +359,10 @@ static int afs_symlink_readpage(struct file *file, struct page *page) · 358 unmodified lines | |||
| 359 | return ret; | 359 | return ret; |
| 360 | } | 360 | } |
| 361 | 361 | ||
| 362 | static void afs_init_request(struct netfs_io_request *rreq, struct file *file) | 362 | static int afs_init_request(struct netfs_io_request *rreq, struct file *file) |
| 363 | { | 363 | { |
| 364 | rreq->netfs_priv = key_get(afs_file_key(file)); | 364 | rreq->netfs_priv = key_get(afs_file_key(file)); |
| 365 | return 0; | ||
| 365 | } | 366 | } |
| 366 | 367 | ||
| 367 | static bool afs_is_cache_enabled(struct inode *inode) | 368 | static bool afs_is_cache_enabled(struct inode *inode) |
| @@ -20,27 +20,34 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, · 19 unmodified lines | |||
| 20 | { | 20 | { |
| 21 | static atomic_t debug_ids; | 21 | static atomic_t debug_ids; |
| 22 | struct netfs_io_request *rreq; | 22 | struct netfs_io_request *rreq; |
| 23 | int ret; | ||
| 23 | 24 | ||
| 24 | rreq = kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); | 25 | rreq = kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); |
| 25 | if (rreq) { | 26 | if (!rreq) |
| 26 | rreq->start = start; | 27 | return ERR_PTR(-ENOMEM); |
| 27 | rreq->len = len; | 28 | |
| 28 | rreq->origin = origin; | 29 | rreq->start = start; |
| 29 | rreq->netfs_ops = ops; | 30 | rreq->len = len; |
| 30 | rreq->netfs_priv = netfs_priv; | 31 | rreq->origin = origin; |
| 31 | rreq->mapping = mapping; | 32 | rreq->netfs_ops = ops; |
| 32 | rreq->inode = file_inode(file); | 33 | rreq->netfs_priv = netfs_priv; |
| 33 | rreq->i_size = i_size_read(rreq->inode); | 34 | rreq->mapping = mapping; |
| 34 | rreq->debug_id = atomic_inc_return(&debug_ids); | 35 | rreq->inode = file_inode(file); |
| 35 | INIT_LIST_HEAD(&rreq->subrequests); | 36 | rreq->i_size = i_size_read(rreq->inode); |
| 36 | INIT_WORK(&rreq->work, netfs_rreq_work); | 37 | rreq->debug_id = atomic_inc_return(&debug_ids); |
| 37 | refcount_set(&rreq->ref, 1); | 38 | INIT_LIST_HEAD(&rreq->subrequests); |
| 38 | __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); | 39 | INIT_WORK(&rreq->work, netfs_rreq_work); |
| 39 | if (ops->init_request) | 40 | refcount_set(&rreq->ref, 1); |
| 40 | ops->init_request(rreq, file); | 41 | __set_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags); |
| 41 | netfs_stat(&netfs_n_rh_rreq); | 42 | if (rreq->netfs_ops->init_request) { |
| 43 | ret = rreq->netfs_ops->init_request(rreq, file); | ||
| 44 | if (ret < 0) { | ||
| 45 | kfree(rreq); | ||
| 46 | return ERR_PTR(ret); | ||
| 47 | } | ||
| 42 | } | 48 | } |
| 43 | 49 | ||
| 50 | netfs_stat(&netfs_n_rh_rreq); | ||
| 44 | return rreq; | 51 | return rreq; |
| 45 | } | 52 | } |
| 46 | 53 | ||
| @@ -768,7 +768,7 @@ void netfs_readahead(struct readahead_control *ractl, · 767 unmodified lines | |||
| 768 | readahead_pos(ractl), | 768 | readahead_pos(ractl), |
| 769 | readahead_length(ractl), | 769 | readahead_length(ractl), |
| 770 | NETFS_READAHEAD); | 770 | NETFS_READAHEAD); |
| 771 | if (!rreq) | 771 | if (IS_ERR(rreq)) |
| 772 | goto cleanup; | 772 | goto cleanup; |
| 773 | 773 | ||
| 774 | if (ops->begin_cache_operation) { | 774 | if (ops->begin_cache_operation) { |
| @@ -842,11 +842,9 @@ int netfs_readpage(struct file *file, · 67 unmodified lines | |||
| 842 | rreq = netfs_alloc_request(folio->mapping, file, ops, netfs_priv, | 842 | rreq = netfs_alloc_request(folio->mapping, file, ops, netfs_priv, |
| 843 | folio_file_pos(folio), folio_size(folio), | 843 | folio_file_pos(folio), folio_size(folio), |
| 844 | NETFS_READPAGE); | 844 | NETFS_READPAGE); |
| 845 | if (!rreq) { | 845 | if (IS_ERR(rreq)) { |
| 846 | if (netfs_priv) | 846 | ret = PTR_ERR(rreq); |
| 847 | ops->cleanup(folio_file_mapping(folio), netfs_priv); | 847 | goto alloc_error; |
| 848 | folio_unlock(folio); | ||
| 849 | return -ENOMEM; | ||
| 850 | } | 848 | } |
| 851 | 849 | ||
| 852 | if (ops->begin_cache_operation) { | 850 | if (ops->begin_cache_operation) { |
| @@ -887,6 +885,11 @@ int netfs_readpage(struct file *file, · 34 unmodified lines | |||
| 887 | out: | 885 | out: |
| 888 | netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); | 886 | netfs_put_request(rreq, false, netfs_rreq_trace_put_hold); |
| 889 | return ret; | 887 | return ret; |
| 888 | alloc_error: | ||
| 889 | if (netfs_priv) | ||
| 890 | ops->cleanup(folio_file_mapping(folio), netfs_priv); | ||
| 891 | folio_unlock(folio); | ||
| 892 | return ret; | ||
| 890 | } | 893 | } |
| 891 | EXPORT_SYMBOL(netfs_readpage); | 894 | EXPORT_SYMBOL(netfs_readpage); |
| 892 | 895 | ||
| @@ -1007,12 +1010,13 @@ retry: · 114 unmodified lines | |||
| 1007 | goto have_folio_no_wait; | 1010 | goto have_folio_no_wait; |
| 1008 | } | 1011 | } |
| 1009 | 1012 | ||
| 1010 | ret = -ENOMEM; | ||
| 1011 | rreq = netfs_alloc_request(mapping, file, ops, netfs_priv, | 1013 | rreq = netfs_alloc_request(mapping, file, ops, netfs_priv, |
| 1012 | folio_file_pos(folio), folio_size(folio), | 1014 | folio_file_pos(folio), folio_size(folio), |
| 1013 | NETFS_READ_FOR_WRITE); | 1015 | NETFS_READ_FOR_WRITE); |
| 1014 | if (!rreq) | 1016 | if (IS_ERR(rreq)) { |
| 1017 | ret = PTR_ERR(rreq); | ||
| 1015 | goto error; | 1018 | goto error; |
| 1019 | } | ||
| 1016 | rreq->no_unlock_folio = folio_index(folio); | 1020 | rreq->no_unlock_folio = folio_index(folio); |
| 1017 | __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); | 1021 | __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); |
| 1018 | netfs_priv = NULL; | 1022 | netfs_priv = NULL; |
| @@ -193,7 +193,7 @@ struct netfs_io_request { · 192 unmodified lines | |||
| 193 | */ | 193 | */ |
| 194 | struct netfs_request_ops { | 194 | struct netfs_request_ops { |
| 195 | bool (*is_cache_enabled)(struct inode *inode); | 195 | bool (*is_cache_enabled)(struct inode *inode); |
| 196 | void (*init_request)(struct netfs_io_request *rreq, struct file *file); | 196 | int (*init_request)(struct netfs_io_request *rreq, struct file *file); |
| 197 | int (*begin_cache_operation)(struct netfs_io_request *rreq); | 197 | int (*begin_cache_operation)(struct netfs_io_request *rreq); |
| 198 | void (*expand_readahead)(struct netfs_io_request *rreq); | 198 | void (*expand_readahead)(struct netfs_io_request *rreq); |
| 199 | bool (*clamp_length)(struct netfs_io_subrequest *subreq); | 199 | bool (*clamp_length)(struct netfs_io_subrequest *subreq); |