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 'nfs-for-6.19-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client fixes from Trond Myklebust:

- Fix another deadlock involving nfs_release_folio()

- localio:
- Stop I/O upon hitting a fatal error
- Deal with page offsets that are > PAGE_SIZE

- Fix size read races in truncate, fallocate and copy offload

- Several bugfixes for the NFSv4.x directory delegation client code

- pNFS:
- Fix a deadlock when returning delegations during open
- Fix memory leaks in various error paths

* tag 'nfs-for-6.19-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
NFS: Fix size read races in truncate, fallocate and copy offload
NFS: Don't immediately return directory delegations when disabled
NFS/localio: Deal with page bases that are > PAGE_SIZE
NFS/localio: Stop further I/O upon hitting an error
NFSv4.x: Directory delegations don't require any state recovery
NFSv4: Don't free slots prematurely if requesting a directory delegation
NFSv4: Fix nfs_clear_verifier_delegated() for delegated directories
NFS: Fix directory delegation verifier checks
pnfs/blocklayout: Fix memory leak in bl_parse_scsi()
pnfs/flexfiles: Fix memory leak in nfs4_ff_alloc_deviceid_node()
NFS: Fix a deadlock involving nfs_release_folio()
pNFS: Fix a deadlock when returning a delegation during open()

+239 -101
+4 -2
fs/nfs/blocklayout/dev.c
··· 417 417 d->map = bl_map_simple; 418 418 d->pr_key = v->scsi.pr_key; 419 419 420 - if (d->len == 0) 421 - return -ENODEV; 420 + if (d->len == 0) { 421 + error = -ENODEV; 422 + goto out_blkdev_put; 423 + } 422 424 423 425 ops = bdev->bd_disk->fops->pr_ops; 424 426 if (!ops) {
+6 -1
fs/nfs/delegation.c
··· 149 149 int nfs4_have_delegation(struct inode *inode, fmode_t type, int flags) 150 150 { 151 151 if (S_ISDIR(inode->i_mode) && !directory_delegations) 152 - nfs_inode_evict_delegation(inode); 152 + nfs4_inode_set_return_delegation_on_close(inode); 153 153 return nfs4_do_check_delegation(inode, type, flags, true); 154 154 } 155 155 ··· 581 581 if (delegation == NULL) 582 582 return 0; 583 583 584 + /* Directory delegations don't require any state recovery */ 585 + if (!S_ISREG(inode->i_mode)) 586 + goto out_return; 587 + 584 588 if (!issync) 585 589 mode |= O_NONBLOCK; 586 590 /* Recall of any remaining application leases */ ··· 608 604 goto out; 609 605 } 610 606 607 + out_return: 611 608 err = nfs_do_return_delegation(inode, delegation, issync); 612 609 out: 613 610 /* Refcount matched in nfs_start_delegation_return_locked() */
+51 -27
fs/nfs/dir.c
··· 1440 1440 1441 1441 if (!dir || !nfs_verify_change_attribute(dir, verf)) 1442 1442 return; 1443 - if (inode && NFS_PROTO(inode)->have_delegation(inode, FMODE_READ, 0)) 1443 + if (NFS_PROTO(dir)->have_delegation(dir, FMODE_READ, 0) || 1444 + (inode && NFS_PROTO(inode)->have_delegation(inode, FMODE_READ, 0))) 1444 1445 nfs_set_verifier_delegated(&verf); 1445 1446 dentry->d_time = verf; 1446 1447 } ··· 1466 1465 EXPORT_SYMBOL_GPL(nfs_set_verifier); 1467 1466 1468 1467 #if IS_ENABLED(CONFIG_NFS_V4) 1468 + static void nfs_clear_verifier_file(struct inode *inode) 1469 + { 1470 + struct dentry *alias; 1471 + struct inode *dir; 1472 + 1473 + hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { 1474 + spin_lock(&alias->d_lock); 1475 + dir = d_inode_rcu(alias->d_parent); 1476 + if (!dir || 1477 + !NFS_PROTO(dir)->have_delegation(dir, FMODE_READ, 0)) 1478 + nfs_unset_verifier_delegated(&alias->d_time); 1479 + spin_unlock(&alias->d_lock); 1480 + } 1481 + } 1482 + 1483 + static void nfs_clear_verifier_directory(struct inode *dir) 1484 + { 1485 + struct dentry *this_parent; 1486 + struct dentry *dentry; 1487 + struct inode *inode; 1488 + 1489 + if (hlist_empty(&dir->i_dentry)) 1490 + return; 1491 + this_parent = 1492 + hlist_entry(dir->i_dentry.first, struct dentry, d_u.d_alias); 1493 + 1494 + spin_lock(&this_parent->d_lock); 1495 + nfs_unset_verifier_delegated(&this_parent->d_time); 1496 + dentry = d_first_child(this_parent); 1497 + hlist_for_each_entry_from(dentry, d_sib) { 1498 + if (unlikely(dentry->d_flags & DCACHE_DENTRY_CURSOR)) 1499 + continue; 1500 + inode = d_inode_rcu(dentry); 1501 + if (inode && 1502 + NFS_PROTO(inode)->have_delegation(inode, FMODE_READ, 0)) 1503 + continue; 1504 + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); 1505 + nfs_unset_verifier_delegated(&dentry->d_time); 1506 + spin_unlock(&dentry->d_lock); 1507 + } 1508 + spin_unlock(&this_parent->d_lock); 1509 + } 1510 + 1469 1511 /** 1470 1512 * nfs_clear_verifier_delegated - clear the dir verifier delegation tag 1471 1513 * @inode: pointer to inode ··· 1521 1477 */ 1522 1478 void nfs_clear_verifier_delegated(struct inode *inode) 1523 1479 { 1524 - struct dentry *alias; 1525 - 1526 1480 if (!inode) 1527 1481 return; 1528 1482 spin_lock(&inode->i_lock); 1529 - hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { 1530 - spin_lock(&alias->d_lock); 1531 - nfs_unset_verifier_delegated(&alias->d_time); 1532 - spin_unlock(&alias->d_lock); 1533 - } 1483 + if (S_ISREG(inode->i_mode)) 1484 + nfs_clear_verifier_file(inode); 1485 + else if (S_ISDIR(inode->i_mode)) 1486 + nfs_clear_verifier_directory(inode); 1534 1487 spin_unlock(&inode->i_lock); 1535 1488 } 1536 1489 EXPORT_SYMBOL_GPL(nfs_clear_verifier_delegated); ··· 1555 1514 if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONE) 1556 1515 return 0; 1557 1516 if (!nfs_dentry_verify_change(dir, dentry)) 1558 - return 0; 1559 - 1560 - /* 1561 - * If we have a directory delegation then we don't need to revalidate 1562 - * the directory. The delegation will either get recalled or we will 1563 - * receive a notification when it changes. 1564 - */ 1565 - if (nfs_have_directory_delegation(dir)) 1566 1517 return 0; 1567 1518 1568 1519 /* Revalidate nfsi->cache_change_attribute before we declare a match */ ··· 2250 2217 EXPORT_SYMBOL_GPL(nfs_atomic_open); 2251 2218 2252 2219 static int 2253 - nfs_lookup_revalidate_delegated_parent(struct inode *dir, struct dentry *dentry, 2254 - struct inode *inode) 2255 - { 2256 - return nfs_lookup_revalidate_done(dir, dentry, inode, 1); 2257 - } 2258 - 2259 - static int 2260 2220 nfs4_lookup_revalidate(struct inode *dir, const struct qstr *name, 2261 2221 struct dentry *dentry, unsigned int flags) 2262 2222 { ··· 2273 2247 if (inode == NULL) 2274 2248 goto full_reval; 2275 2249 2276 - if (nfs_verifier_is_delegated(dentry)) 2250 + if (nfs_verifier_is_delegated(dentry) || 2251 + nfs_have_directory_delegation(inode)) 2277 2252 return nfs_lookup_revalidate_delegated(dir, dentry, inode); 2278 - 2279 - if (nfs_have_directory_delegation(dir)) 2280 - return nfs_lookup_revalidate_delegated_parent(dir, dentry, inode); 2281 2253 2282 2254 /* NFS only supports OPEN on regular files */ 2283 2255 if (!S_ISREG(inode->i_mode))
+2 -1
fs/nfs/file.c
··· 511 511 if ((current_gfp_context(gfp) & GFP_KERNEL) != GFP_KERNEL || 512 512 current_is_kswapd() || current_is_kcompactd()) 513 513 return false; 514 - if (nfs_wb_folio(folio->mapping->host, folio) < 0) 514 + if (nfs_wb_folio_reclaim(folio->mapping->host, folio) < 0 || 515 + folio_test_private(folio)) 515 516 return false; 516 517 } 517 518 return nfs_fscache_release_folio(folio, gfp);
+1 -1
fs/nfs/flexfilelayout/flexfilelayoutdev.c
··· 103 103 sizeof(struct nfs4_ff_ds_version), 104 104 gfp_flags); 105 105 if (!ds_versions) 106 - goto out_scratch; 106 + goto out_err_drain_dsaddrs; 107 107 108 108 for (i = 0; i < version_count; i++) { 109 109 /* 20 = version(4) + minor_version(4) + rsize(4) + wsize(4) +
+6 -4
fs/nfs/inode.c
··· 716 716 { 717 717 struct inode *inode = d_inode(dentry); 718 718 struct nfs_fattr *fattr; 719 - loff_t oldsize = i_size_read(inode); 719 + loff_t oldsize; 720 720 int error = 0; 721 721 kuid_t task_uid = current_fsuid(); 722 722 kuid_t owner_uid = inode->i_uid; ··· 727 727 if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) 728 728 attr->ia_valid &= ~ATTR_MODE; 729 729 730 + if (S_ISREG(inode->i_mode)) 731 + nfs_file_block_o_direct(NFS_I(inode)); 732 + 733 + oldsize = i_size_read(inode); 730 734 if (attr->ia_valid & ATTR_SIZE) { 731 735 BUG_ON(!S_ISREG(inode->i_mode)); 732 736 ··· 778 774 trace_nfs_setattr_enter(inode); 779 775 780 776 /* Write all dirty data */ 781 - if (S_ISREG(inode->i_mode)) { 782 - nfs_file_block_o_direct(NFS_I(inode)); 777 + if (S_ISREG(inode->i_mode)) 783 778 nfs_sync_inode(inode); 784 - } 785 779 786 780 fattr = nfs_alloc_fattr_with_label(NFS_SERVER(inode)); 787 781 if (fattr == NULL) {
+2
fs/nfs/io.c
··· 84 84 nfs_file_block_o_direct(NFS_I(inode)); 85 85 return err; 86 86 } 87 + EXPORT_SYMBOL_GPL(nfs_start_io_write); 87 88 88 89 /** 89 90 * nfs_end_io_write - declare that the buffered write operation is done ··· 98 97 { 99 98 up_write(&inode->i_rwsem); 100 99 } 100 + EXPORT_SYMBOL_GPL(nfs_end_io_write); 101 101 102 102 /* Call with exclusively locked inode->i_rwsem */ 103 103 static void nfs_block_buffered(struct nfs_inode *nfsi, struct inode *inode)
+16 -16
fs/nfs/localio.c
··· 461 461 v = 0; 462 462 total = hdr->args.count; 463 463 base = hdr->args.pgbase; 464 + pagevec += base >> PAGE_SHIFT; 465 + base &= ~PAGE_MASK; 464 466 while (total && v < hdr->page_array.npages) { 465 467 len = min_t(size_t, total, PAGE_SIZE - base); 466 468 bvec_set_page(&iocb->bvec[v], *pagevec, len, base); ··· 620 618 struct nfs_local_kiocb *iocb = 621 619 container_of(work, struct nfs_local_kiocb, work); 622 620 struct file *filp = iocb->kiocb.ki_filp; 623 - bool force_done = false; 624 621 ssize_t status; 625 622 int n_iters; 626 623 ··· 638 637 scoped_with_creds(filp->f_cred) 639 638 status = filp->f_op->read_iter(&iocb->kiocb, &iocb->iters[i]); 640 639 641 - if (status != -EIOCBQUEUED) { 642 - if (unlikely(status >= 0 && status < iocb->iters[i].count)) 643 - force_done = true; /* Partial read */ 644 - if (nfs_local_pgio_done(iocb, status, force_done)) { 645 - nfs_local_read_iocb_done(iocb); 646 - break; 647 - } 640 + if (status == -EIOCBQUEUED) 641 + continue; 642 + /* Break on completion, errors, or short reads */ 643 + if (nfs_local_pgio_done(iocb, status, false) || status < 0 || 644 + (size_t)status < iov_iter_count(&iocb->iters[i])) { 645 + nfs_local_read_iocb_done(iocb); 646 + break; 648 647 } 649 648 } 650 649 } ··· 822 821 container_of(work, struct nfs_local_kiocb, work); 823 822 struct file *filp = iocb->kiocb.ki_filp; 824 823 unsigned long old_flags = current->flags; 825 - bool force_done = false; 826 824 ssize_t status; 827 825 int n_iters; 828 826 ··· 843 843 scoped_with_creds(filp->f_cred) 844 844 status = filp->f_op->write_iter(&iocb->kiocb, &iocb->iters[i]); 845 845 846 - if (status != -EIOCBQUEUED) { 847 - if (unlikely(status >= 0 && status < iocb->iters[i].count)) 848 - force_done = true; /* Partial write */ 849 - if (nfs_local_pgio_done(iocb, status, force_done)) { 850 - nfs_local_write_iocb_done(iocb); 851 - break; 852 - } 846 + if (status == -EIOCBQUEUED) 847 + continue; 848 + /* Break on completion, errors, or short writes */ 849 + if (nfs_local_pgio_done(iocb, status, false) || status < 0 || 850 + (size_t)status < iov_iter_count(&iocb->iters[i])) { 851 + nfs_local_write_iocb_done(iocb); 852 + break; 853 853 } 854 854 } 855 855 file_end_write(filp);
+19 -10
fs/nfs/nfs42proc.c
··· 114 114 exception.inode = inode; 115 115 exception.state = lock->open_context->state; 116 116 117 - nfs_file_block_o_direct(NFS_I(inode)); 118 117 err = nfs_sync_inode(inode); 119 118 if (err) 120 119 goto out; ··· 137 138 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE], 138 139 }; 139 140 struct inode *inode = file_inode(filep); 140 - loff_t oldsize = i_size_read(inode); 141 + loff_t oldsize; 141 142 int err; 142 143 143 144 if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE)) 144 145 return -EOPNOTSUPP; 145 146 146 - inode_lock(inode); 147 + err = nfs_start_io_write(inode); 148 + if (err) 149 + return err; 150 + 151 + oldsize = i_size_read(inode); 147 152 148 153 err = nfs42_proc_fallocate(&msg, filep, offset, len); 149 154 ··· 158 155 NFS_SERVER(inode)->caps &= ~(NFS_CAP_ALLOCATE | 159 156 NFS_CAP_ZERO_RANGE); 160 157 161 - inode_unlock(inode); 158 + nfs_end_io_write(inode); 162 159 return err; 163 160 } 164 161 ··· 173 170 if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE)) 174 171 return -EOPNOTSUPP; 175 172 176 - inode_lock(inode); 173 + err = nfs_start_io_write(inode); 174 + if (err) 175 + return err; 177 176 178 177 err = nfs42_proc_fallocate(&msg, filep, offset, len); 179 178 if (err == 0) ··· 184 179 NFS_SERVER(inode)->caps &= ~(NFS_CAP_DEALLOCATE | 185 180 NFS_CAP_ZERO_RANGE); 186 181 187 - inode_unlock(inode); 182 + nfs_end_io_write(inode); 188 183 return err; 189 184 } 190 185 ··· 194 189 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ZERO_RANGE], 195 190 }; 196 191 struct inode *inode = file_inode(filep); 197 - loff_t oldsize = i_size_read(inode); 192 + loff_t oldsize; 198 193 int err; 199 194 200 195 if (!nfs_server_capable(inode, NFS_CAP_ZERO_RANGE)) 201 196 return -EOPNOTSUPP; 202 197 203 - inode_lock(inode); 198 + err = nfs_start_io_write(inode); 199 + if (err) 200 + return err; 204 201 202 + oldsize = i_size_read(inode); 205 203 err = nfs42_proc_fallocate(&msg, filep, offset, len); 206 204 if (err == 0) { 207 205 nfs_truncate_last_folio(inode->i_mapping, oldsize, ··· 213 205 } else if (err == -EOPNOTSUPP) 214 206 NFS_SERVER(inode)->caps &= ~NFS_CAP_ZERO_RANGE; 215 207 216 - inode_unlock(inode); 208 + nfs_end_io_write(inode); 217 209 return err; 218 210 } 219 211 ··· 424 416 struct nfs_server *src_server = NFS_SERVER(src_inode); 425 417 loff_t pos_src = args->src_pos; 426 418 loff_t pos_dst = args->dst_pos; 427 - loff_t oldsize_dst = i_size_read(dst_inode); 419 + loff_t oldsize_dst; 428 420 size_t count = args->count; 429 421 ssize_t status; 430 422 ··· 469 461 &src_lock->open_context->state->flags); 470 462 set_bit(NFS_CLNT_DST_SSC_COPY_STATE, 471 463 &dst_lock->open_context->state->flags); 464 + oldsize_dst = i_size_read(dst_inode); 472 465 473 466 status = nfs4_call_sync(dst_server->client, dst_server, &msg, 474 467 &args->seq_args, &res->seq_res, 0);
+42 -11
fs/nfs/nfs4proc.c
··· 3894 3894 calldata->res.seqid = calldata->arg.seqid; 3895 3895 calldata->res.server = server; 3896 3896 calldata->res.lr_ret = -NFS4ERR_NOMATCHING_LAYOUT; 3897 - calldata->lr.roc = pnfs_roc(state->inode, 3898 - &calldata->lr.arg, &calldata->lr.res, msg.rpc_cred); 3897 + calldata->lr.roc = pnfs_roc(state->inode, &calldata->lr.arg, 3898 + &calldata->lr.res, msg.rpc_cred, wait); 3899 3899 if (calldata->lr.roc) { 3900 3900 calldata->arg.lr_args = &calldata->lr.arg; 3901 3901 calldata->res.lr_res = &calldata->lr.res; ··· 4494 4494 } 4495 4495 #endif /* CONFIG_NFS_V4_1 */ 4496 4496 4497 + static void nfs4_call_getattr_prepare(struct rpc_task *task, void *calldata) 4498 + { 4499 + struct nfs4_call_sync_data *data = calldata; 4500 + nfs4_setup_sequence(data->seq_server->nfs_client, data->seq_args, 4501 + data->seq_res, task); 4502 + } 4503 + 4504 + static void nfs4_call_getattr_done(struct rpc_task *task, void *calldata) 4505 + { 4506 + struct nfs4_call_sync_data *data = calldata; 4507 + 4508 + nfs4_sequence_process(task, data->seq_res); 4509 + } 4510 + 4511 + static const struct rpc_call_ops nfs4_call_getattr_ops = { 4512 + .rpc_call_prepare = nfs4_call_getattr_prepare, 4513 + .rpc_call_done = nfs4_call_getattr_done, 4514 + }; 4515 + 4497 4516 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, 4498 4517 struct nfs_fattr *fattr, struct inode *inode) 4499 4518 { ··· 4530 4511 .rpc_argp = &args, 4531 4512 .rpc_resp = &res, 4532 4513 }; 4514 + struct nfs4_call_sync_data data = { 4515 + .seq_server = server, 4516 + .seq_args = &args.seq_args, 4517 + .seq_res = &res.seq_res, 4518 + }; 4519 + struct rpc_task_setup task_setup = { 4520 + .rpc_client = server->client, 4521 + .rpc_message = &msg, 4522 + .callback_ops = &nfs4_call_getattr_ops, 4523 + .callback_data = &data, 4524 + }; 4533 4525 struct nfs4_gdd_res gdd_res; 4534 - unsigned short task_flags = 0; 4535 4526 int status; 4536 4527 4537 4528 if (nfs4_has_session(server->nfs_client)) 4538 - task_flags = RPC_TASK_MOVEABLE; 4529 + task_setup.flags = RPC_TASK_MOVEABLE; 4539 4530 4540 4531 /* Is this is an attribute revalidation, subject to softreval? */ 4541 4532 if (inode && (server->flags & NFS_MOUNT_SOFTREVAL)) 4542 - task_flags |= RPC_TASK_TIMEOUT; 4533 + task_setup.flags |= RPC_TASK_TIMEOUT; 4543 4534 4544 4535 args.get_dir_deleg = should_request_dir_deleg(inode); 4545 4536 if (args.get_dir_deleg) ··· 4559 4530 nfs_fattr_init(fattr); 4560 4531 nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 0); 4561 4532 4562 - status = nfs4_do_call_sync(server->client, server, &msg, 4563 - &args.seq_args, &res.seq_res, task_flags); 4533 + status = nfs4_call_sync_custom(&task_setup); 4534 + 4564 4535 if (args.get_dir_deleg) { 4565 4536 switch (status) { 4566 4537 case 0: 4567 4538 if (gdd_res.status != GDD4_OK) 4568 4539 break; 4569 - status = nfs_inode_set_delegation( 4570 - inode, current_cred(), FMODE_READ, 4571 - &gdd_res.deleg, 0, NFS4_OPEN_DELEGATE_READ); 4540 + nfs_inode_set_delegation(inode, current_cred(), 4541 + FMODE_READ, &gdd_res.deleg, 0, 4542 + NFS4_OPEN_DELEGATE_READ); 4572 4543 break; 4573 4544 case -ENOTSUPP: 4574 4545 case -EOPNOTSUPP: 4575 4546 server->caps &= ~NFS_CAP_DIR_DELEG; 4576 4547 } 4577 4548 } 4549 + 4550 + nfs4_sequence_free_slot(&res.seq_res); 4578 4551 return status; 4579 4552 } 4580 4553 ··· 7036 7005 data->inode = nfs_igrab_and_active(inode); 7037 7006 if (data->inode || issync) { 7038 7007 data->lr.roc = pnfs_roc(inode, &data->lr.arg, &data->lr.res, 7039 - cred); 7008 + cred, issync); 7040 7009 if (data->lr.roc) { 7041 7010 data->args.lr_args = &data->lr.arg; 7042 7011 data->res.lr_res = &data->lr.res;
+5 -1
fs/nfs/nfs4state.c
··· 1445 1445 struct nfs4_state *state; 1446 1446 bool found = false; 1447 1447 1448 + if (!S_ISREG(inode->i_mode)) 1449 + goto out; 1448 1450 rcu_read_lock(); 1449 1451 list_for_each_entry_rcu(ctx, &nfsi->open_files, list) { 1450 1452 state = ctx->state; ··· 1468 1466 found = true; 1469 1467 } 1470 1468 rcu_read_unlock(); 1471 - 1469 + out: 1472 1470 nfs_inode_find_delegation_state_and_recover(inode, stateid); 1473 1471 if (found) 1474 1472 nfs4_schedule_state_manager(clp); ··· 1480 1478 struct nfs_inode *nfsi = NFS_I(inode); 1481 1479 struct nfs_open_context *ctx; 1482 1480 1481 + if (!S_ISREG(inode->i_mode)) 1482 + return; 1483 1483 rcu_read_lock(); 1484 1484 list_for_each_entry_rcu(ctx, &nfsi->open_files, list) { 1485 1485 if (ctx->state != state)
+3
fs/nfs/nfstrace.h
··· 1062 1062 DEFINE_NFS_FOLIO_EVENT(nfs_aop_readpage); 1063 1063 DEFINE_NFS_FOLIO_EVENT_DONE(nfs_aop_readpage_done); 1064 1064 1065 + DEFINE_NFS_FOLIO_EVENT(nfs_writeback_folio_reclaim); 1066 + DEFINE_NFS_FOLIO_EVENT_DONE(nfs_writeback_folio_reclaim_done); 1067 + 1065 1068 DEFINE_NFS_FOLIO_EVENT(nfs_writeback_folio); 1066 1069 DEFINE_NFS_FOLIO_EVENT_DONE(nfs_writeback_folio_done); 1067 1070
+41 -17
fs/nfs/pnfs.c
··· 1533 1533 PNFS_FL_LAYOUTRETURN_PRIVILEGED); 1534 1534 } 1535 1535 1536 - bool pnfs_roc(struct inode *ino, 1537 - struct nfs4_layoutreturn_args *args, 1538 - struct nfs4_layoutreturn_res *res, 1539 - const struct cred *cred) 1536 + bool pnfs_roc(struct inode *ino, struct nfs4_layoutreturn_args *args, 1537 + struct nfs4_layoutreturn_res *res, const struct cred *cred, 1538 + bool sync) 1540 1539 { 1541 1540 struct nfs_inode *nfsi = NFS_I(ino); 1542 1541 struct nfs_open_context *ctx; ··· 1546 1547 nfs4_stateid stateid; 1547 1548 enum pnfs_iomode iomode = 0; 1548 1549 bool layoutreturn = false, roc = false; 1549 - bool skip_read = false; 1550 + bool skip_read; 1550 1551 1551 1552 if (!nfs_have_layout(ino)) 1552 1553 return false; ··· 1559 1560 lo = NULL; 1560 1561 goto out_noroc; 1561 1562 } 1562 - pnfs_get_layout_hdr(lo); 1563 - if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) { 1564 - spin_unlock(&ino->i_lock); 1565 - rcu_read_unlock(); 1566 - wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN, 1567 - TASK_UNINTERRUPTIBLE); 1568 - pnfs_put_layout_hdr(lo); 1569 - goto retry; 1570 - } 1571 1563 1572 1564 /* no roc if we hold a delegation */ 1565 + skip_read = false; 1573 1566 if (nfs4_check_delegation(ino, FMODE_READ)) { 1574 - if (nfs4_check_delegation(ino, FMODE_WRITE)) 1567 + if (nfs4_check_delegation(ino, FMODE_WRITE)) { 1568 + lo = NULL; 1575 1569 goto out_noroc; 1570 + } 1576 1571 skip_read = true; 1577 1572 } 1578 1573 ··· 1575 1582 if (state == NULL) 1576 1583 continue; 1577 1584 /* Don't return layout if there is open file state */ 1578 - if (state->state & FMODE_WRITE) 1585 + if (state->state & FMODE_WRITE) { 1586 + lo = NULL; 1579 1587 goto out_noroc; 1588 + } 1580 1589 if (state->state & FMODE_READ) 1581 1590 skip_read = true; 1582 1591 } 1583 1592 1593 + if (skip_read) { 1594 + bool writes = false; 1595 + 1596 + list_for_each_entry(lseg, &lo->plh_segs, pls_list) { 1597 + if (lseg->pls_range.iomode != IOMODE_READ) { 1598 + writes = true; 1599 + break; 1600 + } 1601 + } 1602 + if (!writes) { 1603 + lo = NULL; 1604 + goto out_noroc; 1605 + } 1606 + } 1607 + 1608 + pnfs_get_layout_hdr(lo); 1609 + if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) { 1610 + if (!sync) { 1611 + pnfs_set_plh_return_info( 1612 + lo, skip_read ? IOMODE_RW : IOMODE_ANY, 0); 1613 + goto out_noroc; 1614 + } 1615 + spin_unlock(&ino->i_lock); 1616 + rcu_read_unlock(); 1617 + wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN, 1618 + TASK_UNINTERRUPTIBLE); 1619 + pnfs_put_layout_hdr(lo); 1620 + goto retry; 1621 + } 1584 1622 1585 1623 list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list) { 1586 1624 if (skip_read && lseg->pls_range.iomode == IOMODE_READ) ··· 1651 1627 out_noroc: 1652 1628 spin_unlock(&ino->i_lock); 1653 1629 rcu_read_unlock(); 1654 - pnfs_layoutcommit_inode(ino, true); 1630 + pnfs_layoutcommit_inode(ino, sync); 1655 1631 if (roc) { 1656 1632 struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld; 1657 1633 if (ld->prepare_layoutreturn)
+7 -10
fs/nfs/pnfs.h
··· 303 303 u32 seq); 304 304 int pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, 305 305 struct list_head *lseg_list); 306 - bool pnfs_roc(struct inode *ino, 307 - struct nfs4_layoutreturn_args *args, 308 - struct nfs4_layoutreturn_res *res, 309 - const struct cred *cred); 306 + bool pnfs_roc(struct inode *ino, struct nfs4_layoutreturn_args *args, 307 + struct nfs4_layoutreturn_res *res, const struct cred *cred, 308 + bool sync); 310 309 int pnfs_roc_done(struct rpc_task *task, struct nfs4_layoutreturn_args **argpp, 311 310 struct nfs4_layoutreturn_res **respp, int *ret); 312 311 void pnfs_roc_release(struct nfs4_layoutreturn_args *args, ··· 772 773 return false; 773 774 } 774 775 775 - 776 - static inline bool 777 - pnfs_roc(struct inode *ino, 778 - struct nfs4_layoutreturn_args *args, 779 - struct nfs4_layoutreturn_res *res, 780 - const struct cred *cred) 776 + static inline bool pnfs_roc(struct inode *ino, 777 + struct nfs4_layoutreturn_args *args, 778 + struct nfs4_layoutreturn_res *res, 779 + const struct cred *cred, bool sync) 781 780 { 782 781 return false; 783 782 }
+33
fs/nfs/write.c
··· 2025 2025 } 2026 2026 2027 2027 /** 2028 + * nfs_wb_folio_reclaim - Write back all requests on one page 2029 + * @inode: pointer to page 2030 + * @folio: pointer to folio 2031 + * 2032 + * Assumes that the folio has been locked by the caller 2033 + */ 2034 + int nfs_wb_folio_reclaim(struct inode *inode, struct folio *folio) 2035 + { 2036 + loff_t range_start = folio_pos(folio); 2037 + size_t len = folio_size(folio); 2038 + struct writeback_control wbc = { 2039 + .sync_mode = WB_SYNC_ALL, 2040 + .nr_to_write = 0, 2041 + .range_start = range_start, 2042 + .range_end = range_start + len - 1, 2043 + .for_sync = 1, 2044 + }; 2045 + int ret; 2046 + 2047 + if (folio_test_writeback(folio)) 2048 + return -EBUSY; 2049 + if (folio_clear_dirty_for_io(folio)) { 2050 + trace_nfs_writeback_folio_reclaim(inode, range_start, len); 2051 + ret = nfs_writepage_locked(folio, &wbc); 2052 + trace_nfs_writeback_folio_reclaim_done(inode, range_start, len, 2053 + ret); 2054 + return ret; 2055 + } 2056 + nfs_commit_inode(inode, 0); 2057 + return 0; 2058 + } 2059 + 2060 + /** 2028 2061 * nfs_wb_folio - Write back all requests on one page 2029 2062 * @inode: pointer to page 2030 2063 * @folio: pointer to folio
+1
include/linux/nfs_fs.h
··· 637 637 extern int nfs_sync_inode(struct inode *inode); 638 638 extern int nfs_wb_all(struct inode *inode); 639 639 extern int nfs_wb_folio(struct inode *inode, struct folio *folio); 640 + extern int nfs_wb_folio_reclaim(struct inode *inode, struct folio *folio); 640 641 int nfs_wb_folio_cancel(struct inode *inode, struct folio *folio); 641 642 extern int nfs_commit_inode(struct inode *, int); 642 643 extern struct nfs_commit_data *nfs_commitdata_alloc(void);