These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / nfs / delegation.c
index 029d688..5166adc 100644 (file)
@@ -113,7 +113,8 @@ out:
        return status;
 }
 
-static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
+static int nfs_delegation_claim_opens(struct inode *inode,
+               const nfs4_stateid *stateid, fmode_t type)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_open_context *ctx;
@@ -140,7 +141,7 @@ again:
                /* Block nfs4_proc_unlck */
                mutex_lock(&sp->so_delegreturn_mutex);
                seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
-               err = nfs4_open_delegation_recall(ctx, state, stateid);
+               err = nfs4_open_delegation_recall(ctx, state, stateid, type);
                if (!err)
                        err = nfs_delegation_claim_locks(ctx, state, stateid);
                if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
@@ -175,7 +176,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
                if (delegation->inode != NULL) {
                        nfs4_stateid_copy(&delegation->stateid, &res->delegation);
                        delegation->type = res->delegation_type;
-                       delegation->maxsize = res->maxsize;
+                       delegation->pagemod_limit = res->pagemod_limit;
                        oldcred = delegation->cred;
                        delegation->cred = get_rpccred(cred);
                        clear_bit(NFS_DELEGATION_NEED_RECLAIM,
@@ -337,7 +338,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
                return -ENOMEM;
        nfs4_stateid_copy(&delegation->stateid, &res->delegation);
        delegation->type = res->delegation_type;
-       delegation->maxsize = res->maxsize;
+       delegation->pagemod_limit = res->pagemod_limit;
        delegation->change_attr = inode->i_version;
        delegation->cred = get_rpccred(cred);
        delegation->inode = inode;
@@ -411,7 +412,8 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
        do {
                if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
                        break;
-               err = nfs_delegation_claim_opens(inode, &delegation->stateid);
+               err = nfs_delegation_claim_opens(inode, &delegation->stateid,
+                               delegation->type);
                if (!issync || err != -EAGAIN)
                        break;
                /*
@@ -719,14 +721,12 @@ int nfs_async_inode_return_delegation(struct inode *inode,
        struct nfs_client *clp = server->nfs_client;
        struct nfs_delegation *delegation;
 
-       filemap_flush(inode->i_mapping);
-
        rcu_read_lock();
        delegation = rcu_dereference(NFS_I(inode)->delegation);
        if (delegation == NULL)
                goto out_enoent;
-
-       if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid))
+       if (stateid != NULL &&
+           !clp->cl_mvops->match_stateid(&delegation->stateid, stateid))
                goto out_enoent;
        nfs_mark_return_delegation(server, delegation);
        rcu_read_unlock();
@@ -900,3 +900,28 @@ bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode,
        rcu_read_unlock();
        return ret;
 }
+
+/**
+ * nfs4_delegation_flush_on_close - Check if we must flush file on close
+ * @inode: inode to check
+ *
+ * This function checks the number of outstanding writes to the file
+ * against the delegation 'space_limit' field to see if
+ * the spec requires us to flush the file on close.
+ */
+bool nfs4_delegation_flush_on_close(const struct inode *inode)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct nfs_delegation *delegation;
+       bool ret = true;
+
+       rcu_read_lock();
+       delegation = rcu_dereference(nfsi->delegation);
+       if (delegation == NULL || !(delegation->type & FMODE_WRITE))
+               goto out;
+       if (nfsi->nrequests < delegation->pagemod_limit)
+               ret = false;
+out:
+       rcu_read_unlock();
+       return ret;
+}