| .. | .. |
|---|
| 26 | 26 | struct cb_getattrargs *args = argp; |
|---|
| 27 | 27 | struct cb_getattrres *res = resp; |
|---|
| 28 | 28 | struct nfs_delegation *delegation; |
|---|
| 29 | | - struct nfs_inode *nfsi; |
|---|
| 30 | 29 | struct inode *inode; |
|---|
| 31 | 30 | |
|---|
| 32 | 31 | res->status = htonl(NFS4ERR_OP_NOT_IN_SESSION); |
|---|
| .. | .. |
|---|
| 47 | 46 | -ntohl(res->status)); |
|---|
| 48 | 47 | goto out; |
|---|
| 49 | 48 | } |
|---|
| 50 | | - nfsi = NFS_I(inode); |
|---|
| 51 | 49 | rcu_read_lock(); |
|---|
| 52 | | - delegation = rcu_dereference(nfsi->delegation); |
|---|
| 50 | + delegation = nfs4_get_valid_delegation(inode); |
|---|
| 53 | 51 | if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0) |
|---|
| 54 | 52 | goto out_iput; |
|---|
| 55 | 53 | res->size = i_size_read(inode); |
|---|
| 56 | 54 | res->change_attr = delegation->change_attr; |
|---|
| 57 | 55 | if (nfs_have_writebacks(inode)) |
|---|
| 58 | 56 | res->change_attr++; |
|---|
| 59 | | - res->ctime = timespec64_to_timespec(inode->i_ctime); |
|---|
| 60 | | - res->mtime = timespec64_to_timespec(inode->i_mtime); |
|---|
| 57 | + res->ctime = inode->i_ctime; |
|---|
| 58 | + res->mtime = inode->i_mtime; |
|---|
| 61 | 59 | res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) & |
|---|
| 62 | 60 | args->bitmap[0]; |
|---|
| 63 | 61 | res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) & |
|---|
| .. | .. |
|---|
| 123 | 121 | */ |
|---|
| 124 | 122 | static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp, |
|---|
| 125 | 123 | const nfs4_stateid *stateid) |
|---|
| 124 | + __must_hold(RCU) |
|---|
| 126 | 125 | { |
|---|
| 127 | 126 | struct nfs_server *server; |
|---|
| 128 | 127 | struct inode *inode; |
|---|
| 129 | 128 | struct pnfs_layout_hdr *lo; |
|---|
| 130 | 129 | |
|---|
| 130 | + rcu_read_lock(); |
|---|
| 131 | 131 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
|---|
| 132 | | - list_for_each_entry(lo, &server->layouts, plh_layouts) { |
|---|
| 132 | + list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) { |
|---|
| 133 | 133 | if (!pnfs_layout_is_valid(lo)) |
|---|
| 134 | 134 | continue; |
|---|
| 135 | | - if (stateid != NULL && |
|---|
| 136 | | - !nfs4_stateid_match_other(stateid, &lo->plh_stateid)) |
|---|
| 135 | + if (!nfs4_stateid_match_other(stateid, &lo->plh_stateid)) |
|---|
| 137 | 136 | continue; |
|---|
| 138 | | - inode = igrab(lo->plh_inode); |
|---|
| 139 | | - if (!inode) |
|---|
| 140 | | - return ERR_PTR(-EAGAIN); |
|---|
| 141 | | - if (!nfs_sb_active(inode->i_sb)) { |
|---|
| 142 | | - rcu_read_unlock(); |
|---|
| 143 | | - spin_unlock(&clp->cl_lock); |
|---|
| 144 | | - iput(inode); |
|---|
| 145 | | - spin_lock(&clp->cl_lock); |
|---|
| 146 | | - rcu_read_lock(); |
|---|
| 147 | | - return ERR_PTR(-EAGAIN); |
|---|
| 148 | | - } |
|---|
| 149 | | - return inode; |
|---|
| 137 | + if (nfs_sb_active(server->super)) |
|---|
| 138 | + inode = igrab(lo->plh_inode); |
|---|
| 139 | + else |
|---|
| 140 | + inode = ERR_PTR(-EAGAIN); |
|---|
| 141 | + rcu_read_unlock(); |
|---|
| 142 | + if (inode) |
|---|
| 143 | + return inode; |
|---|
| 144 | + nfs_sb_deactive(server->super); |
|---|
| 145 | + return ERR_PTR(-EAGAIN); |
|---|
| 150 | 146 | } |
|---|
| 151 | 147 | } |
|---|
| 152 | | - |
|---|
| 148 | + rcu_read_unlock(); |
|---|
| 153 | 149 | return ERR_PTR(-ENOENT); |
|---|
| 154 | 150 | } |
|---|
| 155 | 151 | |
|---|
| .. | .. |
|---|
| 167 | 163 | struct inode *inode; |
|---|
| 168 | 164 | struct pnfs_layout_hdr *lo; |
|---|
| 169 | 165 | |
|---|
| 166 | + rcu_read_lock(); |
|---|
| 170 | 167 | list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { |
|---|
| 171 | | - list_for_each_entry(lo, &server->layouts, plh_layouts) { |
|---|
| 168 | + list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) { |
|---|
| 172 | 169 | nfsi = NFS_I(lo->plh_inode); |
|---|
| 173 | 170 | if (nfs_compare_fh(fh, &nfsi->fh)) |
|---|
| 174 | 171 | continue; |
|---|
| 175 | 172 | if (nfsi->layout != lo) |
|---|
| 176 | 173 | continue; |
|---|
| 177 | | - inode = igrab(lo->plh_inode); |
|---|
| 178 | | - if (!inode) |
|---|
| 179 | | - return ERR_PTR(-EAGAIN); |
|---|
| 180 | | - if (!nfs_sb_active(inode->i_sb)) { |
|---|
| 181 | | - rcu_read_unlock(); |
|---|
| 182 | | - spin_unlock(&clp->cl_lock); |
|---|
| 183 | | - iput(inode); |
|---|
| 184 | | - spin_lock(&clp->cl_lock); |
|---|
| 185 | | - rcu_read_lock(); |
|---|
| 186 | | - return ERR_PTR(-EAGAIN); |
|---|
| 187 | | - } |
|---|
| 188 | | - return inode; |
|---|
| 174 | + if (nfs_sb_active(server->super)) |
|---|
| 175 | + inode = igrab(lo->plh_inode); |
|---|
| 176 | + else |
|---|
| 177 | + inode = ERR_PTR(-EAGAIN); |
|---|
| 178 | + rcu_read_unlock(); |
|---|
| 179 | + if (inode) |
|---|
| 180 | + return inode; |
|---|
| 181 | + nfs_sb_deactive(server->super); |
|---|
| 182 | + return ERR_PTR(-EAGAIN); |
|---|
| 189 | 183 | } |
|---|
| 190 | 184 | } |
|---|
| 191 | | - |
|---|
| 185 | + rcu_read_unlock(); |
|---|
| 192 | 186 | return ERR_PTR(-ENOENT); |
|---|
| 193 | 187 | } |
|---|
| 194 | 188 | |
|---|
| .. | .. |
|---|
| 198 | 192 | { |
|---|
| 199 | 193 | struct inode *inode; |
|---|
| 200 | 194 | |
|---|
| 201 | | - spin_lock(&clp->cl_lock); |
|---|
| 202 | | - rcu_read_lock(); |
|---|
| 203 | 195 | inode = nfs_layout_find_inode_by_stateid(clp, stateid); |
|---|
| 204 | 196 | if (inode == ERR_PTR(-ENOENT)) |
|---|
| 205 | 197 | inode = nfs_layout_find_inode_by_fh(clp, fh); |
|---|
| 206 | | - rcu_read_unlock(); |
|---|
| 207 | | - spin_unlock(&clp->cl_lock); |
|---|
| 208 | | - |
|---|
| 209 | 198 | return inode; |
|---|
| 210 | 199 | } |
|---|
| 211 | 200 | |
|---|
| .. | .. |
|---|
| 284 | 273 | goto unlock; |
|---|
| 285 | 274 | } |
|---|
| 286 | 275 | |
|---|
| 287 | | - pnfs_set_layout_stateid(lo, &args->cbl_stateid, true); |
|---|
| 276 | + pnfs_set_layout_stateid(lo, &args->cbl_stateid, NULL, true); |
|---|
| 288 | 277 | switch (pnfs_mark_matching_lsegs_return(lo, &free_me_list, |
|---|
| 289 | 278 | &args->cbl_range, |
|---|
| 290 | 279 | be32_to_cpu(args->cbl_stateid.seqid))) { |
|---|
| .. | .. |
|---|
| 294 | 283 | rv = NFS4_OK; |
|---|
| 295 | 284 | break; |
|---|
| 296 | 285 | case -ENOENT: |
|---|
| 286 | + set_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags); |
|---|
| 297 | 287 | /* Embrace your forgetfulness! */ |
|---|
| 298 | 288 | rv = NFS4ERR_NOMATCHING_LAYOUT; |
|---|
| 299 | 289 | |
|---|
| .. | .. |
|---|
| 364 | 354 | struct cb_process_state *cps) |
|---|
| 365 | 355 | { |
|---|
| 366 | 356 | struct cb_devicenotifyargs *args = argp; |
|---|
| 357 | + const struct pnfs_layoutdriver_type *ld = NULL; |
|---|
| 367 | 358 | uint32_t i; |
|---|
| 368 | 359 | __be32 res = 0; |
|---|
| 369 | | - struct nfs_client *clp = cps->clp; |
|---|
| 370 | | - struct nfs_server *server = NULL; |
|---|
| 371 | 360 | |
|---|
| 372 | | - if (!clp) { |
|---|
| 361 | + if (!cps->clp) { |
|---|
| 373 | 362 | res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION); |
|---|
| 374 | 363 | goto out; |
|---|
| 375 | 364 | } |
|---|
| .. | .. |
|---|
| 377 | 366 | for (i = 0; i < args->ndevs; i++) { |
|---|
| 378 | 367 | struct cb_devicenotifyitem *dev = &args->devs[i]; |
|---|
| 379 | 368 | |
|---|
| 380 | | - if (!server || |
|---|
| 381 | | - server->pnfs_curr_ld->id != dev->cbd_layout_type) { |
|---|
| 382 | | - rcu_read_lock(); |
|---|
| 383 | | - list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) |
|---|
| 384 | | - if (server->pnfs_curr_ld && |
|---|
| 385 | | - server->pnfs_curr_ld->id == dev->cbd_layout_type) { |
|---|
| 386 | | - rcu_read_unlock(); |
|---|
| 387 | | - goto found; |
|---|
| 388 | | - } |
|---|
| 389 | | - rcu_read_unlock(); |
|---|
| 390 | | - continue; |
|---|
| 369 | + if (!ld || ld->id != dev->cbd_layout_type) { |
|---|
| 370 | + pnfs_put_layoutdriver(ld); |
|---|
| 371 | + ld = pnfs_find_layoutdriver(dev->cbd_layout_type); |
|---|
| 372 | + if (!ld) |
|---|
| 373 | + continue; |
|---|
| 391 | 374 | } |
|---|
| 392 | | - |
|---|
| 393 | | - found: |
|---|
| 394 | | - nfs4_delete_deviceid(server->pnfs_curr_ld, clp, &dev->cbd_dev_id); |
|---|
| 375 | + nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id); |
|---|
| 395 | 376 | } |
|---|
| 396 | | - |
|---|
| 377 | + pnfs_put_layoutdriver(ld); |
|---|
| 397 | 378 | out: |
|---|
| 398 | 379 | kfree(args->devs); |
|---|
| 399 | 380 | return res; |
|---|
| .. | .. |
|---|
| 416 | 397 | validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot, |
|---|
| 417 | 398 | const struct cb_sequenceargs * args) |
|---|
| 418 | 399 | { |
|---|
| 400 | + __be32 ret; |
|---|
| 401 | + |
|---|
| 402 | + ret = cpu_to_be32(NFS4ERR_BADSLOT); |
|---|
| 419 | 403 | if (args->csa_slotid > tbl->server_highest_slotid) |
|---|
| 420 | | - return htonl(NFS4ERR_BADSLOT); |
|---|
| 404 | + goto out_err; |
|---|
| 421 | 405 | |
|---|
| 422 | 406 | /* Replay */ |
|---|
| 423 | 407 | if (args->csa_sequenceid == slot->seq_nr) { |
|---|
| 408 | + ret = cpu_to_be32(NFS4ERR_DELAY); |
|---|
| 424 | 409 | if (nfs4_test_locked_slot(tbl, slot->slot_nr)) |
|---|
| 425 | | - return htonl(NFS4ERR_DELAY); |
|---|
| 410 | + goto out_err; |
|---|
| 411 | + |
|---|
| 426 | 412 | /* Signal process_op to set this error on next op */ |
|---|
| 413 | + ret = cpu_to_be32(NFS4ERR_RETRY_UNCACHED_REP); |
|---|
| 427 | 414 | if (args->csa_cachethis == 0) |
|---|
| 428 | | - return htonl(NFS4ERR_RETRY_UNCACHED_REP); |
|---|
| 415 | + goto out_err; |
|---|
| 429 | 416 | |
|---|
| 430 | 417 | /* Liar! We never allowed you to set csa_cachethis != 0 */ |
|---|
| 431 | | - return htonl(NFS4ERR_SEQ_FALSE_RETRY); |
|---|
| 418 | + ret = cpu_to_be32(NFS4ERR_SEQ_FALSE_RETRY); |
|---|
| 419 | + goto out_err; |
|---|
| 432 | 420 | } |
|---|
| 433 | 421 | |
|---|
| 434 | 422 | /* Note: wraparound relies on seq_nr being of type u32 */ |
|---|
| 435 | | - if (likely(args->csa_sequenceid == slot->seq_nr + 1)) |
|---|
| 436 | | - return htonl(NFS4_OK); |
|---|
| 437 | | - |
|---|
| 438 | 423 | /* Misordered request */ |
|---|
| 439 | | - return htonl(NFS4ERR_SEQ_MISORDERED); |
|---|
| 424 | + ret = cpu_to_be32(NFS4ERR_SEQ_MISORDERED); |
|---|
| 425 | + if (args->csa_sequenceid != slot->seq_nr + 1) |
|---|
| 426 | + goto out_err; |
|---|
| 427 | + |
|---|
| 428 | + return cpu_to_be32(NFS4_OK); |
|---|
| 429 | + |
|---|
| 430 | +out_err: |
|---|
| 431 | + trace_nfs4_cb_seqid_err(args, ret); |
|---|
| 432 | + return ret; |
|---|
| 440 | 433 | } |
|---|
| 441 | 434 | |
|---|
| 442 | 435 | /* |
|---|
| .. | .. |
|---|
| 597 | 590 | struct cb_recallanyargs *args = argp; |
|---|
| 598 | 591 | __be32 status; |
|---|
| 599 | 592 | fmode_t flags = 0; |
|---|
| 593 | + bool schedule_manager = false; |
|---|
| 600 | 594 | |
|---|
| 601 | 595 | status = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION); |
|---|
| 602 | 596 | if (!cps->clp) /* set in cb_sequence */ |
|---|
| .. | .. |
|---|
| 619 | 613 | |
|---|
| 620 | 614 | if (args->craa_type_mask & BIT(RCA4_TYPE_MASK_FILE_LAYOUT)) |
|---|
| 621 | 615 | pnfs_recall_all_layouts(cps->clp); |
|---|
| 616 | + |
|---|
| 617 | + if (args->craa_type_mask & BIT(PNFS_FF_RCA4_TYPE_MASK_READ)) { |
|---|
| 618 | + set_bit(NFS4CLNT_RECALL_ANY_LAYOUT_READ, &cps->clp->cl_state); |
|---|
| 619 | + schedule_manager = true; |
|---|
| 620 | + } |
|---|
| 621 | + if (args->craa_type_mask & BIT(PNFS_FF_RCA4_TYPE_MASK_RW)) { |
|---|
| 622 | + set_bit(NFS4CLNT_RECALL_ANY_LAYOUT_RW, &cps->clp->cl_state); |
|---|
| 623 | + schedule_manager = true; |
|---|
| 624 | + } |
|---|
| 625 | + if (schedule_manager) |
|---|
| 626 | + nfs4_schedule_state_manager(cps->clp); |
|---|
| 627 | + |
|---|
| 622 | 628 | out: |
|---|
| 623 | 629 | dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); |
|---|
| 624 | 630 | return status; |
|---|