Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'vfs-6.17-rc8.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs fixes from Christian Brauner:

- Prevent double unlock in netfs

- Fix a NULL pointer dereference in afs_put_server()

- Fix a reference leak in netfs

* tag 'vfs-6.17-rc8.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
netfs: fix reference leak
afs: Fix potential null pointer dereference in afs_put_server
netfs: Prevent duplicate unlocking

+50 -16
+2 -1
fs/afs/server.c
··· 331 331 void afs_put_server(struct afs_net *net, struct afs_server *server, 332 332 enum afs_server_trace reason) 333 333 { 334 - unsigned int a, debug_id = server->debug_id; 334 + unsigned int a, debug_id; 335 335 bool zero; 336 336 int r; 337 337 338 338 if (!server) 339 339 return; 340 340 341 + debug_id = server->debug_id; 341 342 a = atomic_read(&server->active); 342 343 zero = __refcount_dec_and_test(&server->ref, &r); 343 344 trace_afs_server(debug_id, r - 1, a, reason);
+5 -5
fs/netfs/buffered_read.c
··· 369 369 return netfs_put_request(rreq, netfs_rreq_trace_put_return); 370 370 371 371 cleanup_free: 372 - return netfs_put_request(rreq, netfs_rreq_trace_put_failed); 372 + return netfs_put_failed_request(rreq); 373 373 } 374 374 EXPORT_SYMBOL(netfs_readahead); 375 375 ··· 472 472 return ret < 0 ? ret : 0; 473 473 474 474 discard: 475 - netfs_put_request(rreq, netfs_rreq_trace_put_discard); 475 + netfs_put_failed_request(rreq); 476 476 alloc_error: 477 477 folio_unlock(folio); 478 478 return ret; ··· 532 532 return ret < 0 ? ret : 0; 533 533 534 534 discard: 535 - netfs_put_request(rreq, netfs_rreq_trace_put_discard); 535 + netfs_put_failed_request(rreq); 536 536 alloc_error: 537 537 folio_unlock(folio); 538 538 return ret; ··· 699 699 return 0; 700 700 701 701 error_put: 702 - netfs_put_request(rreq, netfs_rreq_trace_put_failed); 702 + netfs_put_failed_request(rreq); 703 703 error: 704 704 if (folio) { 705 705 folio_unlock(folio); ··· 754 754 return ret < 0 ? ret : 0; 755 755 756 756 error_put: 757 - netfs_put_request(rreq, netfs_rreq_trace_put_discard); 757 + netfs_put_failed_request(rreq); 758 758 error: 759 759 _leave(" = %d", ret); 760 760 return ret;
+1 -1
fs/netfs/buffered_write.c
··· 347 347 folio_put(folio); 348 348 ret = filemap_write_and_wait_range(mapping, fpos, fpos + flen - 1); 349 349 if (ret < 0) 350 - goto error_folio_unlock; 350 + goto out; 351 351 continue; 352 352 353 353 copied:
+6 -1
fs/netfs/direct_read.c
··· 131 131 132 132 if (rreq->len == 0) { 133 133 pr_err("Zero-sized read [R=%x]\n", rreq->debug_id); 134 + netfs_put_request(rreq, netfs_rreq_trace_put_discard); 134 135 return -EIO; 135 136 } 136 137 ··· 206 205 if (user_backed_iter(iter)) { 207 206 ret = netfs_extract_user_iter(iter, rreq->len, &rreq->buffer.iter, 0); 208 207 if (ret < 0) 209 - goto out; 208 + goto error_put; 210 209 rreq->direct_bv = (struct bio_vec *)rreq->buffer.iter.bvec; 211 210 rreq->direct_bv_count = ret; 212 211 rreq->direct_bv_unpin = iov_iter_extract_will_pin(iter); ··· 238 237 netfs_put_request(rreq, netfs_rreq_trace_put_return); 239 238 if (ret > 0) 240 239 orig_count -= ret; 240 + return ret; 241 + 242 + error_put: 243 + netfs_put_failed_request(rreq); 241 244 return ret; 242 245 } 243 246 EXPORT_SYMBOL(netfs_unbuffered_read_iter_locked);
+5 -1
fs/netfs/direct_write.c
··· 57 57 n = netfs_extract_user_iter(iter, len, &wreq->buffer.iter, 0); 58 58 if (n < 0) { 59 59 ret = n; 60 - goto out; 60 + goto error_put; 61 61 } 62 62 wreq->direct_bv = (struct bio_vec *)wreq->buffer.iter.bvec; 63 63 wreq->direct_bv_count = n; ··· 100 100 101 101 out: 102 102 netfs_put_request(wreq, netfs_rreq_trace_put_return); 103 + return ret; 104 + 105 + error_put: 106 + netfs_put_failed_request(wreq); 103 107 return ret; 104 108 } 105 109 EXPORT_SYMBOL(netfs_unbuffered_write_iter_locked);
+1
fs/netfs/internal.h
··· 87 87 void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_trace what); 88 88 void netfs_clear_subrequests(struct netfs_io_request *rreq); 89 89 void netfs_put_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_trace what); 90 + void netfs_put_failed_request(struct netfs_io_request *rreq); 90 91 struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq); 91 92 92 93 static inline void netfs_see_request(struct netfs_io_request *rreq,
+27 -3
fs/netfs/objects.c
··· 116 116 netfs_stat_d(&netfs_n_rh_rreq); 117 117 } 118 118 119 - static void netfs_free_request(struct work_struct *work) 119 + static void netfs_deinit_request(struct netfs_io_request *rreq) 120 120 { 121 - struct netfs_io_request *rreq = 122 - container_of(work, struct netfs_io_request, cleanup_work); 123 121 struct netfs_inode *ictx = netfs_inode(rreq->inode); 124 122 unsigned int i; 125 123 ··· 147 149 148 150 if (atomic_dec_and_test(&ictx->io_count)) 149 151 wake_up_var(&ictx->io_count); 152 + } 153 + 154 + static void netfs_free_request(struct work_struct *work) 155 + { 156 + struct netfs_io_request *rreq = 157 + container_of(work, struct netfs_io_request, cleanup_work); 158 + 159 + netfs_deinit_request(rreq); 150 160 call_rcu(&rreq->rcu, netfs_free_request_rcu); 151 161 } 152 162 ··· 171 165 if (dead) 172 166 WARN_ON(!queue_work(system_unbound_wq, &rreq->cleanup_work)); 173 167 } 168 + } 169 + 170 + /* 171 + * Free a request (synchronously) that was just allocated but has 172 + * failed before it could be submitted. 173 + */ 174 + void netfs_put_failed_request(struct netfs_io_request *rreq) 175 + { 176 + int r = refcount_read(&rreq->ref); 177 + 178 + /* new requests have two references (see 179 + * netfs_alloc_request(), and this function is only allowed on 180 + * new request objects 181 + */ 182 + WARN_ON_ONCE(r != 2); 183 + 184 + trace_netfs_rreq_ref(rreq->debug_id, r, netfs_rreq_trace_put_failed); 185 + netfs_free_request(&rreq->cleanup_work); 174 186 } 175 187 176 188 /*
+1 -1
fs/netfs/read_pgpriv2.c
··· 118 118 return creq; 119 119 120 120 cancel_put: 121 - netfs_put_request(creq, netfs_rreq_trace_put_return); 121 + netfs_put_failed_request(creq); 122 122 cancel: 123 123 rreq->copy_to_cache = ERR_PTR(-ENOBUFS); 124 124 clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags);
+1 -1
fs/netfs/read_single.c
··· 189 189 return ret; 190 190 191 191 cleanup_free: 192 - netfs_put_request(rreq, netfs_rreq_trace_put_failed); 192 + netfs_put_failed_request(rreq); 193 193 return ret; 194 194 } 195 195 EXPORT_SYMBOL(netfs_read_single);
+1 -2
fs/netfs/write_issue.c
··· 133 133 134 134 return wreq; 135 135 nomem: 136 - wreq->error = -ENOMEM; 137 - netfs_put_request(wreq, netfs_rreq_trace_put_failed); 136 + netfs_put_failed_request(wreq); 138 137 return ERR_PTR(-ENOMEM); 139 138 } 140 139