| .. | .. |
|---|
| 110 | 110 | .rpc_resp = fattr, |
|---|
| 111 | 111 | }; |
|---|
| 112 | 112 | int status; |
|---|
| 113 | + unsigned short task_flags = 0; |
|---|
| 114 | + |
|---|
| 115 | + /* Is this is an attribute revalidation, subject to softreval? */ |
|---|
| 116 | + if (inode && (server->flags & NFS_MOUNT_SOFTREVAL)) |
|---|
| 117 | + task_flags |= RPC_TASK_TIMEOUT; |
|---|
| 113 | 118 | |
|---|
| 114 | 119 | dprintk("NFS call getattr\n"); |
|---|
| 115 | 120 | nfs_fattr_init(fattr); |
|---|
| 116 | | - status = rpc_call_sync(server->client, &msg, 0); |
|---|
| 121 | + status = rpc_call_sync(server->client, &msg, task_flags); |
|---|
| 117 | 122 | dprintk("NFS reply getattr: %d\n", status); |
|---|
| 118 | 123 | return status; |
|---|
| 119 | 124 | } |
|---|
| .. | .. |
|---|
| 140 | 145 | nfs_fattr_init(fattr); |
|---|
| 141 | 146 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
|---|
| 142 | 147 | if (status == 0) { |
|---|
| 148 | + nfs_setattr_update_inode(inode, sattr, fattr); |
|---|
| 143 | 149 | if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL) |
|---|
| 144 | 150 | nfs_zap_acl_cache(inode); |
|---|
| 145 | | - nfs_setattr_update_inode(inode, sattr, fattr); |
|---|
| 146 | 151 | } |
|---|
| 147 | 152 | dprintk("NFS reply setattr: %d\n", status); |
|---|
| 148 | 153 | return status; |
|---|
| 149 | 154 | } |
|---|
| 150 | 155 | |
|---|
| 151 | 156 | static int |
|---|
| 152 | | -nfs3_proc_lookup(struct inode *dir, const struct qstr *name, |
|---|
| 157 | +nfs3_proc_lookup(struct inode *dir, struct dentry *dentry, |
|---|
| 153 | 158 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, |
|---|
| 154 | 159 | struct nfs4_label *label) |
|---|
| 155 | 160 | { |
|---|
| 156 | 161 | struct nfs3_diropargs arg = { |
|---|
| 157 | 162 | .fh = NFS_FH(dir), |
|---|
| 158 | | - .name = name->name, |
|---|
| 159 | | - .len = name->len |
|---|
| 163 | + .name = dentry->d_name.name, |
|---|
| 164 | + .len = dentry->d_name.len |
|---|
| 160 | 165 | }; |
|---|
| 161 | 166 | struct nfs3_diropres res = { |
|---|
| 162 | 167 | .fh = fhandle, |
|---|
| .. | .. |
|---|
| 168 | 173 | .rpc_resp = &res, |
|---|
| 169 | 174 | }; |
|---|
| 170 | 175 | int status; |
|---|
| 176 | + unsigned short task_flags = 0; |
|---|
| 171 | 177 | |
|---|
| 172 | | - dprintk("NFS call lookup %s\n", name->name); |
|---|
| 178 | + /* Is this is an attribute revalidation, subject to softreval? */ |
|---|
| 179 | + if (nfs_lookup_is_soft_revalidate(dentry)) |
|---|
| 180 | + task_flags |= RPC_TASK_TIMEOUT; |
|---|
| 181 | + |
|---|
| 173 | 182 | res.dir_attr = nfs_alloc_fattr(); |
|---|
| 174 | 183 | if (res.dir_attr == NULL) |
|---|
| 175 | 184 | return -ENOMEM; |
|---|
| 176 | 185 | |
|---|
| 186 | + dprintk("NFS call lookup %pd2\n", dentry); |
|---|
| 177 | 187 | nfs_fattr_init(fattr); |
|---|
| 178 | | - status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
|---|
| 188 | + status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags); |
|---|
| 179 | 189 | nfs_refresh_inode(dir, res.dir_attr); |
|---|
| 180 | 190 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) { |
|---|
| 181 | 191 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; |
|---|
| 182 | 192 | msg.rpc_argp = fhandle; |
|---|
| 183 | 193 | msg.rpc_resp = fattr; |
|---|
| 184 | | - status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
|---|
| 194 | + status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags); |
|---|
| 185 | 195 | } |
|---|
| 186 | 196 | nfs_free_fattr(res.dir_attr); |
|---|
| 187 | 197 | dprintk("NFS reply lookup: %d\n", status); |
|---|
| .. | .. |
|---|
| 279 | 289 | return data; |
|---|
| 280 | 290 | } |
|---|
| 281 | 291 | |
|---|
| 282 | | -static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_createdata *data) |
|---|
| 292 | +static struct dentry * |
|---|
| 293 | +nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_createdata *data) |
|---|
| 283 | 294 | { |
|---|
| 284 | 295 | int status; |
|---|
| 285 | 296 | |
|---|
| 286 | 297 | status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0); |
|---|
| 287 | 298 | nfs_post_op_update_inode(dir, data->res.dir_attr); |
|---|
| 288 | | - if (status == 0) |
|---|
| 289 | | - status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL); |
|---|
| 290 | | - return status; |
|---|
| 299 | + if (status != 0) |
|---|
| 300 | + return ERR_PTR(status); |
|---|
| 301 | + |
|---|
| 302 | + return nfs_add_or_obtain(dentry, data->res.fh, data->res.fattr, NULL); |
|---|
| 291 | 303 | } |
|---|
| 292 | 304 | |
|---|
| 293 | 305 | static void nfs3_free_createdata(struct nfs3_createdata *data) |
|---|
| .. | .. |
|---|
| 304 | 316 | { |
|---|
| 305 | 317 | struct posix_acl *default_acl, *acl; |
|---|
| 306 | 318 | struct nfs3_createdata *data; |
|---|
| 319 | + struct dentry *d_alias; |
|---|
| 307 | 320 | int status = -ENOMEM; |
|---|
| 308 | 321 | |
|---|
| 309 | 322 | dprintk("NFS call create %pd\n", dentry); |
|---|
| .. | .. |
|---|
| 330 | 343 | goto out; |
|---|
| 331 | 344 | |
|---|
| 332 | 345 | for (;;) { |
|---|
| 333 | | - status = nfs3_do_create(dir, dentry, data); |
|---|
| 346 | + d_alias = nfs3_do_create(dir, dentry, data); |
|---|
| 347 | + status = PTR_ERR_OR_ZERO(d_alias); |
|---|
| 334 | 348 | |
|---|
| 335 | 349 | if (status != -ENOTSUPP) |
|---|
| 336 | 350 | break; |
|---|
| .. | .. |
|---|
| 355 | 369 | if (status != 0) |
|---|
| 356 | 370 | goto out_release_acls; |
|---|
| 357 | 371 | |
|---|
| 372 | + if (d_alias) |
|---|
| 373 | + dentry = d_alias; |
|---|
| 374 | + |
|---|
| 358 | 375 | /* When we created the file with exclusive semantics, make |
|---|
| 359 | 376 | * sure we set the attributes afterwards. */ |
|---|
| 360 | 377 | if (data->arg.create.createmode == NFS3_CREATE_EXCLUSIVE) { |
|---|
| .. | .. |
|---|
| 372 | 389 | nfs_post_op_update_inode(d_inode(dentry), data->res.fattr); |
|---|
| 373 | 390 | dprintk("NFS reply setattr (post-create): %d\n", status); |
|---|
| 374 | 391 | if (status != 0) |
|---|
| 375 | | - goto out_release_acls; |
|---|
| 392 | + goto out_dput; |
|---|
| 376 | 393 | } |
|---|
| 377 | 394 | |
|---|
| 378 | 395 | status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl); |
|---|
| 379 | 396 | |
|---|
| 397 | +out_dput: |
|---|
| 398 | + dput(d_alias); |
|---|
| 380 | 399 | out_release_acls: |
|---|
| 381 | 400 | posix_acl_release(acl); |
|---|
| 382 | 401 | posix_acl_release(default_acl); |
|---|
| .. | .. |
|---|
| 504 | 523 | unsigned int len, struct iattr *sattr) |
|---|
| 505 | 524 | { |
|---|
| 506 | 525 | struct nfs3_createdata *data; |
|---|
| 526 | + struct dentry *d_alias; |
|---|
| 507 | 527 | int status = -ENOMEM; |
|---|
| 508 | 528 | |
|---|
| 509 | 529 | if (len > NFS3_MAXPATHLEN) |
|---|
| .. | .. |
|---|
| 522 | 542 | data->arg.symlink.pathlen = len; |
|---|
| 523 | 543 | data->arg.symlink.sattr = sattr; |
|---|
| 524 | 544 | |
|---|
| 525 | | - status = nfs3_do_create(dir, dentry, data); |
|---|
| 545 | + d_alias = nfs3_do_create(dir, dentry, data); |
|---|
| 546 | + status = PTR_ERR_OR_ZERO(d_alias); |
|---|
| 547 | + |
|---|
| 548 | + if (status == 0) |
|---|
| 549 | + dput(d_alias); |
|---|
| 526 | 550 | |
|---|
| 527 | 551 | nfs3_free_createdata(data); |
|---|
| 528 | 552 | out: |
|---|
| .. | .. |
|---|
| 535 | 559 | { |
|---|
| 536 | 560 | struct posix_acl *default_acl, *acl; |
|---|
| 537 | 561 | struct nfs3_createdata *data; |
|---|
| 562 | + struct dentry *d_alias; |
|---|
| 538 | 563 | int status = -ENOMEM; |
|---|
| 539 | 564 | |
|---|
| 540 | 565 | dprintk("NFS call mkdir %pd\n", dentry); |
|---|
| .. | .. |
|---|
| 553 | 578 | data->arg.mkdir.len = dentry->d_name.len; |
|---|
| 554 | 579 | data->arg.mkdir.sattr = sattr; |
|---|
| 555 | 580 | |
|---|
| 556 | | - status = nfs3_do_create(dir, dentry, data); |
|---|
| 581 | + d_alias = nfs3_do_create(dir, dentry, data); |
|---|
| 582 | + status = PTR_ERR_OR_ZERO(d_alias); |
|---|
| 583 | + |
|---|
| 557 | 584 | if (status != 0) |
|---|
| 558 | 585 | goto out_release_acls; |
|---|
| 559 | 586 | |
|---|
| 587 | + if (d_alias) |
|---|
| 588 | + dentry = d_alias; |
|---|
| 589 | + |
|---|
| 560 | 590 | status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl); |
|---|
| 561 | 591 | |
|---|
| 592 | + dput(d_alias); |
|---|
| 562 | 593 | out_release_acls: |
|---|
| 563 | 594 | posix_acl_release(acl); |
|---|
| 564 | 595 | posix_acl_release(default_acl); |
|---|
| .. | .. |
|---|
| 607 | 638 | * readdirplus. |
|---|
| 608 | 639 | */ |
|---|
| 609 | 640 | static int |
|---|
| 610 | | -nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, |
|---|
| 641 | +nfs3_proc_readdir(struct dentry *dentry, const struct cred *cred, |
|---|
| 611 | 642 | u64 cookie, struct page **pages, unsigned int count, bool plus) |
|---|
| 612 | 643 | { |
|---|
| 613 | 644 | struct inode *dir = d_inode(dentry); |
|---|
| .. | .. |
|---|
| 628 | 659 | .rpc_proc = &nfs3_procedures[NFS3PROC_READDIR], |
|---|
| 629 | 660 | .rpc_argp = &arg, |
|---|
| 630 | 661 | .rpc_resp = &res, |
|---|
| 631 | | - .rpc_cred = cred |
|---|
| 662 | + .rpc_cred = cred, |
|---|
| 632 | 663 | }; |
|---|
| 633 | 664 | int status = -ENOMEM; |
|---|
| 634 | 665 | |
|---|
| .. | .. |
|---|
| 660 | 691 | { |
|---|
| 661 | 692 | struct posix_acl *default_acl, *acl; |
|---|
| 662 | 693 | struct nfs3_createdata *data; |
|---|
| 694 | + struct dentry *d_alias; |
|---|
| 663 | 695 | int status = -ENOMEM; |
|---|
| 664 | 696 | |
|---|
| 665 | 697 | dprintk("NFS call mknod %pd %u:%u\n", dentry, |
|---|
| .. | .. |
|---|
| 698 | 730 | goto out_release_acls; |
|---|
| 699 | 731 | } |
|---|
| 700 | 732 | |
|---|
| 701 | | - status = nfs3_do_create(dir, dentry, data); |
|---|
| 733 | + d_alias = nfs3_do_create(dir, dentry, data); |
|---|
| 734 | + status = PTR_ERR_OR_ZERO(d_alias); |
|---|
| 702 | 735 | if (status != 0) |
|---|
| 703 | 736 | goto out_release_acls; |
|---|
| 704 | 737 | |
|---|
| 738 | + if (d_alias) |
|---|
| 739 | + dentry = d_alias; |
|---|
| 740 | + |
|---|
| 705 | 741 | status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl); |
|---|
| 706 | 742 | |
|---|
| 743 | + dput(d_alias); |
|---|
| 707 | 744 | out_release_acls: |
|---|
| 708 | 745 | posix_acl_release(acl); |
|---|
| 709 | 746 | posix_acl_release(default_acl); |
|---|
| .. | .. |
|---|
| 786 | 823 | static int nfs3_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr) |
|---|
| 787 | 824 | { |
|---|
| 788 | 825 | struct inode *inode = hdr->inode; |
|---|
| 826 | + struct nfs_server *server = NFS_SERVER(inode); |
|---|
| 789 | 827 | |
|---|
| 790 | 828 | if (hdr->pgio_done_cb != NULL) |
|---|
| 791 | 829 | return hdr->pgio_done_cb(task, hdr); |
|---|
| 792 | 830 | |
|---|
| 793 | 831 | if (nfs3_async_handle_jukebox(task, inode)) |
|---|
| 794 | 832 | return -EAGAIN; |
|---|
| 833 | + |
|---|
| 834 | + if (task->tk_status >= 0 && !server->read_hdrsize) |
|---|
| 835 | + cmpxchg(&server->read_hdrsize, 0, hdr->res.replen); |
|---|
| 795 | 836 | |
|---|
| 796 | 837 | nfs_invalidate_atime(inode); |
|---|
| 797 | 838 | nfs_refresh_inode(inode, &hdr->fattr); |
|---|
| .. | .. |
|---|
| 802 | 843 | struct rpc_message *msg) |
|---|
| 803 | 844 | { |
|---|
| 804 | 845 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; |
|---|
| 846 | + hdr->args.replen = NFS_SERVER(hdr->inode)->read_hdrsize; |
|---|
| 805 | 847 | } |
|---|
| 806 | 848 | |
|---|
| 807 | 849 | static int nfs3_proc_pgio_rpc_prepare(struct rpc_task *task, |
|---|
| .. | .. |
|---|
| 958 | 1000 | .nlmclnt_ops = &nlmclnt_fl_close_lock_ops, |
|---|
| 959 | 1001 | .getroot = nfs3_proc_get_root, |
|---|
| 960 | 1002 | .submount = nfs_submount, |
|---|
| 961 | | - .try_mount = nfs_try_mount, |
|---|
| 1003 | + .try_get_tree = nfs_try_get_tree, |
|---|
| 962 | 1004 | .getattr = nfs3_proc_getattr, |
|---|
| 963 | 1005 | .setattr = nfs3_proc_setattr, |
|---|
| 964 | 1006 | .lookup = nfs3_proc_lookup, |
|---|