Commit 072e5135 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-5.20-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client fixes from Trond Myklebust:
"Stable fixes:
   - NFS: Fix another fsync() issue after a server reboot

  Bugfixes:
   - NFS: unlink/rmdir shouldn't call d_delete() twice on ENOENT
   - NFS: Fix missing unlock in nfs_unlink()
   - Add sanity checking of the file type used by __nfs42_ssc_open
   - Fix a case where we're failing to set task->tk_rpc_status

  Cleanups:
   - Remove the NFS_CONTEXT_RESEND_WRITES flag that got obsoleted by the
     fsync() fix"

* tag 'nfs-for-5.20-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  SUNRPC: RPC level errors should set task->tk_rpc_status
  NFSv4.2 fix problems with __nfs42_ssc_open
  NFS: unlink/rmdir shouldn't call d_delete() twice on ENOENT
  NFS: Cleanup to remove unused flag NFS_CONTEXT_RESEND_WRITES
  NFS: Remove a bogus flag setting in pnfs_write_done_resend_to_mds
  NFS: Fix another fsync() issue after a server reboot
  NFS: Fix missing unlock in nfs_unlink()
parents d3cd67d6 ed06fce0
...@@ -2382,7 +2382,8 @@ static void nfs_dentry_remove_handle_error(struct inode *dir, ...@@ -2382,7 +2382,8 @@ static void nfs_dentry_remove_handle_error(struct inode *dir,
{ {
switch (error) { switch (error) {
case -ENOENT: case -ENOENT:
d_delete(dentry); if (d_really_is_positive(dentry))
d_delete(dentry);
nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
break; break;
case 0: case 0:
...@@ -2484,8 +2485,10 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -2484,8 +2485,10 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
*/ */
error = -ETXTBSY; error = -ETXTBSY;
if (WARN_ON(dentry->d_flags & DCACHE_NFSFS_RENAMED) || if (WARN_ON(dentry->d_flags & DCACHE_NFSFS_RENAMED) ||
WARN_ON(dentry->d_fsdata == NFS_FSDATA_BLOCKED)) WARN_ON(dentry->d_fsdata == NFS_FSDATA_BLOCKED)) {
spin_unlock(&dentry->d_lock);
goto out; goto out;
}
if (dentry->d_fsdata) if (dentry->d_fsdata)
/* old devname */ /* old devname */
kfree(dentry->d_fsdata); kfree(dentry->d_fsdata);
......
...@@ -221,8 +221,10 @@ nfs_file_fsync_commit(struct file *file, int datasync) ...@@ -221,8 +221,10 @@ nfs_file_fsync_commit(struct file *file, int datasync)
int int
nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{ {
struct nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct nfs_inode *nfsi = NFS_I(inode);
long save_nredirtied = atomic_long_read(&nfsi->redirtied_pages);
long nredirtied;
int ret; int ret;
trace_nfs_fsync_enter(inode); trace_nfs_fsync_enter(inode);
...@@ -237,15 +239,10 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) ...@@ -237,15 +239,10 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
ret = pnfs_sync_inode(inode, !!datasync); ret = pnfs_sync_inode(inode, !!datasync);
if (ret != 0) if (ret != 0)
break; break;
if (!test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags)) nredirtied = atomic_long_read(&nfsi->redirtied_pages);
if (nredirtied == save_nredirtied)
break; break;
/* save_nredirtied = nredirtied;
* If nfs_file_fsync_commit detected a server reboot, then
* resend all dirty pages that might have been covered by
* the NFS_CONTEXT_RESEND_WRITES flag
*/
start = 0;
end = LLONG_MAX;
} }
trace_nfs_fsync_exit(inode, ret); trace_nfs_fsync_exit(inode, ret);
......
...@@ -426,6 +426,7 @@ nfs_ilookup(struct super_block *sb, struct nfs_fattr *fattr, struct nfs_fh *fh) ...@@ -426,6 +426,7 @@ nfs_ilookup(struct super_block *sb, struct nfs_fattr *fattr, struct nfs_fh *fh)
static void nfs_inode_init_regular(struct nfs_inode *nfsi) static void nfs_inode_init_regular(struct nfs_inode *nfsi)
{ {
atomic_long_set(&nfsi->nrequests, 0); atomic_long_set(&nfsi->nrequests, 0);
atomic_long_set(&nfsi->redirtied_pages, 0);
INIT_LIST_HEAD(&nfsi->commit_info.list); INIT_LIST_HEAD(&nfsi->commit_info.list);
atomic_long_set(&nfsi->commit_info.ncommit, 0); atomic_long_set(&nfsi->commit_info.ncommit, 0);
atomic_set(&nfsi->commit_info.rpcs_out, 0); atomic_set(&nfsi->commit_info.rpcs_out, 0);
......
...@@ -340,6 +340,11 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt, ...@@ -340,6 +340,11 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
goto out; goto out;
} }
if (!S_ISREG(fattr->mode)) {
res = ERR_PTR(-EBADF);
goto out;
}
res = ERR_PTR(-ENOMEM); res = ERR_PTR(-ENOMEM);
len = strlen(SSC_READ_NAME_BODY) + 16; len = strlen(SSC_READ_NAME_BODY) + 16;
read_name = kzalloc(len, GFP_KERNEL); read_name = kzalloc(len, GFP_KERNEL);
...@@ -357,6 +362,7 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt, ...@@ -357,6 +362,7 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
r_ino->i_fop); r_ino->i_fop);
if (IS_ERR(filep)) { if (IS_ERR(filep)) {
res = ERR_CAST(filep); res = ERR_CAST(filep);
iput(r_ino);
goto out_free_name; goto out_free_name;
} }
......
...@@ -2817,7 +2817,6 @@ int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *hdr) ...@@ -2817,7 +2817,6 @@ int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *hdr)
/* Resend all requests through the MDS */ /* Resend all requests through the MDS */
nfs_pageio_init_write(&pgio, hdr->inode, FLUSH_STABLE, true, nfs_pageio_init_write(&pgio, hdr->inode, FLUSH_STABLE, true,
hdr->completion_ops); hdr->completion_ops);
set_bit(NFS_CONTEXT_RESEND_WRITES, &hdr->args.context->flags);
return nfs_pageio_resend(&pgio, hdr); return nfs_pageio_resend(&pgio, hdr);
} }
EXPORT_SYMBOL_GPL(pnfs_write_done_resend_to_mds); EXPORT_SYMBOL_GPL(pnfs_write_done_resend_to_mds);
......
...@@ -1420,10 +1420,12 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr, ...@@ -1420,10 +1420,12 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
*/ */
static void nfs_redirty_request(struct nfs_page *req) 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 */ /* Bump the transmission count */
req->wb_nio++; req->wb_nio++;
nfs_mark_request_dirty(req); 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_end_page_writeback(req);
nfs_release_request(req); nfs_release_request(req);
} }
...@@ -1904,7 +1906,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data) ...@@ -1904,7 +1906,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
/* We have a mismatch. Write the page again */ /* We have a mismatch. Write the page again */
dprintk_cont(" mismatch\n"); dprintk_cont(" mismatch\n");
nfs_mark_request_dirty(req); 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: next:
nfs_unlock_and_release_request(req); nfs_unlock_and_release_request(req);
/* Latency breaker */ /* Latency breaker */
......
...@@ -83,7 +83,6 @@ struct nfs_open_context { ...@@ -83,7 +83,6 @@ struct nfs_open_context {
fmode_t mode; fmode_t mode;
unsigned long flags; unsigned long flags;
#define NFS_CONTEXT_RESEND_WRITES (1)
#define NFS_CONTEXT_BAD (2) #define NFS_CONTEXT_BAD (2)
#define NFS_CONTEXT_UNLOCK (3) #define NFS_CONTEXT_UNLOCK (3)
#define NFS_CONTEXT_FILE_OPEN (4) #define NFS_CONTEXT_FILE_OPEN (4)
...@@ -182,6 +181,7 @@ struct nfs_inode { ...@@ -182,6 +181,7 @@ struct nfs_inode {
/* Regular file */ /* Regular file */
struct { struct {
atomic_long_t nrequests; atomic_long_t nrequests;
atomic_long_t redirtied_pages;
struct nfs_mds_commit_info commit_info; struct nfs_mds_commit_info commit_info;
struct mutex commit_mutex; struct mutex commit_mutex;
}; };
......
...@@ -1902,7 +1902,7 @@ call_encode(struct rpc_task *task) ...@@ -1902,7 +1902,7 @@ call_encode(struct rpc_task *task)
break; break;
case -EKEYEXPIRED: case -EKEYEXPIRED:
if (!task->tk_cred_retry) { if (!task->tk_cred_retry) {
rpc_exit(task, task->tk_status); rpc_call_rpcerror(task, task->tk_status);
} else { } else {
task->tk_action = call_refresh; task->tk_action = call_refresh;
task->tk_cred_retry--; task->tk_cred_retry--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment