diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 31f7082df49f..3791c9d84dad 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1547,6 +1547,24 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid) | |||
1547 | return NULL; | 1547 | return NULL; |
1548 | } | 1548 | } |
1549 | 1549 | ||
1550 | static void | ||
1551 | nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open, | ||
1552 | struct nfs4_delegation **dp) | ||
1553 | { | ||
1554 | int flags; | ||
1555 | int status; | ||
1556 | |||
1557 | *dp = find_delegation_file(fp, &open->op_delegate_stateid); | ||
1558 | if (*dp == NULL) | ||
1559 | return; | ||
1560 | flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ? | ||
1561 | RD_STATE : WR_STATE; | ||
1562 | status = nfs4_check_delegmode(*dp, flags); | ||
1563 | if (status) | ||
1564 | *dp = NULL; | ||
1565 | return; | ||
1566 | } | ||
1567 | |||
1550 | static int | 1568 | static int |
1551 | nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp) | 1569 | nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp) |
1552 | { | 1570 | { |
@@ -1572,21 +1590,28 @@ out: | |||
1572 | 1590 | ||
1573 | static int | 1591 | static int |
1574 | nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, | 1592 | nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, |
1593 | struct nfs4_delegation *dp, | ||
1575 | struct svc_fh *cur_fh, int flags) | 1594 | struct svc_fh *cur_fh, int flags) |
1576 | { | 1595 | { |
1577 | struct nfs4_stateid *stp; | 1596 | struct nfs4_stateid *stp; |
1578 | int status; | ||
1579 | 1597 | ||
1580 | stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL); | 1598 | stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL); |
1581 | if (stp == NULL) | 1599 | if (stp == NULL) |
1582 | return nfserr_resource; | 1600 | return nfserr_resource; |
1583 | 1601 | ||
1584 | status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file); | 1602 | if (dp) { |
1585 | if (status) { | 1603 | get_file(dp->dl_vfs_file); |
1586 | if (status == nfserr_dropit) | 1604 | stp->st_vfs_file = dp->dl_vfs_file; |
1587 | status = nfserr_jukebox; | 1605 | } else { |
1588 | kfree(stp); | 1606 | int status; |
1589 | return status; | 1607 | status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, |
1608 | &stp->st_vfs_file); | ||
1609 | if (status) { | ||
1610 | if (status == nfserr_dropit) | ||
1611 | status = nfserr_jukebox; | ||
1612 | kfree(stp); | ||
1613 | return status; | ||
1614 | } | ||
1590 | } | 1615 | } |
1591 | vfsopen++; | 1616 | vfsopen++; |
1592 | *stpp = stp; | 1617 | *stpp = stp; |
@@ -1720,6 +1745,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1720 | struct nfs4_file *fp = NULL; | 1745 | struct nfs4_file *fp = NULL; |
1721 | struct inode *ino = current_fh->fh_dentry->d_inode; | 1746 | struct inode *ino = current_fh->fh_dentry->d_inode; |
1722 | struct nfs4_stateid *stp = NULL; | 1747 | struct nfs4_stateid *stp = NULL; |
1748 | struct nfs4_delegation *dp = NULL; | ||
1723 | int status; | 1749 | int status; |
1724 | 1750 | ||
1725 | status = nfserr_inval; | 1751 | status = nfserr_inval; |
@@ -1734,6 +1760,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1734 | if (fp) { | 1760 | if (fp) { |
1735 | if ((status = nfs4_check_open(fp, open, &stp))) | 1761 | if ((status = nfs4_check_open(fp, open, &stp))) |
1736 | goto out; | 1762 | goto out; |
1763 | nfs4_check_deleg(fp, open, &dp); | ||
1737 | } else { | 1764 | } else { |
1738 | status = nfserr_resource; | 1765 | status = nfserr_resource; |
1739 | fp = alloc_init_file(ino); | 1766 | fp = alloc_init_file(ino); |
@@ -1757,7 +1784,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1757 | flags = MAY_WRITE; | 1784 | flags = MAY_WRITE; |
1758 | else | 1785 | else |
1759 | flags = MAY_READ; | 1786 | flags = MAY_READ; |
1760 | if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags))) | 1787 | status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags); |
1788 | if (status) | ||
1761 | goto out; | 1789 | goto out; |
1762 | init_stateid(stp, fp, open); | 1790 | init_stateid(stp, fp, open); |
1763 | status = nfsd4_truncate(rqstp, current_fh, open); | 1791 | status = nfsd4_truncate(rqstp, current_fh, open); |