NFSv4.2: Update mode bits after ALLOCATE and DEALLOCATE
[linux-block.git] / fs / nfs / write.c
index 1c706465d090b095b98c900d8b5fe7cb407af57e..27a3d20233536569d20fe918e88f83fc9bde4239 100644 (file)
@@ -592,7 +592,8 @@ nfs_lock_and_join_requests(struct page *page)
 
 static void nfs_write_error(struct nfs_page *req, int error)
 {
-       trace_nfs_write_error(req, error);
+       trace_nfs_write_error(page_file_mapping(req->wb_page)->host, req,
+                             error);
        nfs_mapping_set_error(req->wb_page, error);
        nfs_inode_remove_request(req);
        nfs_end_page_writeback(req);
@@ -1000,7 +1001,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
                nfs_list_remove_request(req);
                if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) &&
                    (hdr->good_bytes < bytes)) {
-                       trace_nfs_comp_error(req, hdr->error);
+                       trace_nfs_comp_error(hdr->inode, req, hdr->error);
                        nfs_mapping_set_error(req->wb_page, hdr->error);
                        goto remove_req;
                }
@@ -1419,10 +1420,12 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
  */
 static void nfs_redirty_request(struct nfs_page *req)
 {
+       struct nfs_inode *nfsi = NFS_I(page_file_mapping(req->wb_page)->host);
+
        /* Bump the transmission count */
        req->wb_nio++;
        nfs_mark_request_dirty(req);
-       set_bit(NFS_CONTEXT_RESEND_WRITES, &nfs_req_openctx(req)->flags);
+       atomic_long_inc(&nfsi->redirtied_pages);
        nfs_end_page_writeback(req);
        nfs_release_request(req);
 }
@@ -1444,8 +1447,6 @@ static void nfs_async_write_error(struct list_head *head, int error)
 static void nfs_async_write_reschedule_io(struct nfs_pgio_header *hdr)
 {
        nfs_async_write_error(&hdr->pages, 0);
-       filemap_fdatawrite_range(hdr->inode->i_mapping, hdr->args.offset,
-                       hdr->args.offset + hdr->args.count - 1);
 }
 
 static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = {
@@ -1495,31 +1496,6 @@ void nfs_commit_prepare(struct rpc_task *task, void *calldata)
        NFS_PROTO(data->inode)->commit_rpc_prepare(task, data);
 }
 
-/*
- * Special version of should_remove_suid() that ignores capabilities.
- */
-static int nfs_should_remove_suid(const struct inode *inode)
-{
-       umode_t mode = inode->i_mode;
-       int kill = 0;
-
-       /* suid always must be killed */
-       if (unlikely(mode & S_ISUID))
-               kill = ATTR_KILL_SUID;
-
-       /*
-        * sgid without any exec bits is just a mandatory locking mark; leave
-        * it alone.  If some exec bits are set, it's a real sgid; kill it.
-        */
-       if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
-               kill |= ATTR_KILL_SGID;
-
-       if (unlikely(kill && S_ISREG(mode)))
-               return kill;
-
-       return 0;
-}
-
 static void nfs_writeback_check_extend(struct nfs_pgio_header *hdr,
                struct nfs_fattr *fattr)
 {
@@ -1576,25 +1552,37 @@ static int nfs_writeback_done(struct rpc_task *task,
        nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count);
        trace_nfs_writeback_done(task, hdr);
 
-       if (hdr->res.verf->committed < hdr->args.stable &&
-           task->tk_status >= 0) {
-               /* We tried a write call, but the server did not
-                * commit data to stable storage even though we
-                * requested it.
-                * Note: There is a known bug in Tru64 < 5.0 in which
-                *       the server reports NFS_DATA_SYNC, but performs
-                *       NFS_FILE_SYNC. We therefore implement this checking
-                *       as a dprintk() in order to avoid filling syslog.
-                */
-               static unsigned long    complain;
+       if (task->tk_status >= 0) {
+               enum nfs3_stable_how committed = hdr->res.verf->committed;
+
+               if (committed == NFS_UNSTABLE) {
+                       /*
+                        * We have some uncommitted data on the server at
+                        * this point, so ensure that we keep track of that
+                        * fact irrespective of what later writes do.
+                        */
+                       set_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags);
+               }
 
-               /* Note this will print the MDS for a DS write */
-               if (time_before(complain, jiffies)) {
-                       dprintk("NFS:       faulty NFS server %s:"
-                               " (committed = %d) != (stable = %d)\n",
-                               NFS_SERVER(inode)->nfs_client->cl_hostname,
-                               hdr->res.verf->committed, hdr->args.stable);
-                       complain = jiffies + 300 * HZ;
+               if (committed < hdr->args.stable) {
+                       /* We tried a write call, but the server did not
+                        * commit data to stable storage even though we
+                        * requested it.
+                        * Note: There is a known bug in Tru64 < 5.0 in which
+                        *       the server reports NFS_DATA_SYNC, but performs
+                        *       NFS_FILE_SYNC. We therefore implement this checking
+                        *       as a dprintk() in order to avoid filling syslog.
+                        */
+                       static unsigned long    complain;
+
+                       /* Note this will print the MDS for a DS write */
+                       if (time_before(complain, jiffies)) {
+                               dprintk("NFS:       faulty NFS server %s:"
+                                       " (committed = %d) != (stable = %d)\n",
+                                       NFS_SERVER(inode)->nfs_client->cl_hostname,
+                                       committed, hdr->args.stable);
+                               complain = jiffies + 300 * HZ;
+                       }
                }
        }
 
@@ -1872,7 +1860,8 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
                        (long long)req_offset(req));
                if (status < 0) {
                        if (req->wb_page) {
-                               trace_nfs_commit_error(req, status);
+                               trace_nfs_commit_error(data->inode, req,
+                                                      status);
                                nfs_mapping_set_error(req->wb_page, status);
                                nfs_inode_remove_request(req);
                        }
@@ -1892,7 +1881,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
                /* We have a mismatch. Write the page again */
                dprintk_cont(" mismatch\n");
                nfs_mark_request_dirty(req);
-               set_bit(NFS_CONTEXT_RESEND_WRITES, &nfs_req_openctx(req)->flags);
+               atomic_long_inc(&NFS_I(data->inode)->redirtied_pages);
        next:
                nfs_unlock_and_release_request(req);
                /* Latency breaker */