Merge tag 'nfsd-5.9' of git://git.linux-nfs.org/projects/cel/cel-2.6
Pull NFS server updates from Chuck Lever: "Highlights: - Support for user extended attributes on NFS (RFC 8276) - Further reduce unnecessary NFSv4 delegation recalls Notable fixes: - Fix recent krb5p regression - Address a few resource leaks and a rare NULL dereference Other: - De-duplicate RPC/RDMA error handling and other utility functions - Replace storage and display of kernel memory addresses by tracepoints" * tag 'nfsd-5.9' of git://git.linux-nfs.org/projects/cel/cel-2.6: (38 commits) svcrdma: CM event handler clean up svcrdma: Remove transport reference counting svcrdma: Fix another Receive buffer leak SUNRPC: Refresh the show_rqstp_flags() macro nfsd: netns.h: delete a duplicated word SUNRPC: Fix ("SUNRPC: Add "@len" parameter to gss_unwrap()") nfsd: avoid a NULL dereference in __cld_pipe_upcall() nfsd4: a client's own opens needn't prevent delegations nfsd: Use seq_putc() in two functions svcrdma: Display chunk completion ID when posting a rw_ctxt svcrdma: Record send_ctxt completion ID in trace_svcrdma_post_send() svcrdma: Introduce Send completion IDs svcrdma: Record Receive completion ID in svc_rdma_decode_rqst svcrdma: Introduce Receive completion IDs svcrdma: Introduce infrastructure to support completion IDs svcrdma: Add common XDR encoders for RDMA and Read segments svcrdma: Add common XDR decoders for RDMA and Read segments SUNRPC: Add helpers for decoding list discriminators symbolically svcrdma: Remove declarations for functions long removed svcrdma: Clean up trace_svcrdma_send_failed() tracepoint ...
此提交包含在:
@@ -4940,6 +4940,32 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp,
|
||||
return fl;
|
||||
}
|
||||
|
||||
static int nfsd4_check_conflicting_opens(struct nfs4_client *clp,
|
||||
struct nfs4_file *fp)
|
||||
{
|
||||
struct nfs4_clnt_odstate *co;
|
||||
struct file *f = fp->fi_deleg_file->nf_file;
|
||||
struct inode *ino = locks_inode(f);
|
||||
int writes = atomic_read(&ino->i_writecount);
|
||||
|
||||
if (fp->fi_fds[O_WRONLY])
|
||||
writes--;
|
||||
if (fp->fi_fds[O_RDWR])
|
||||
writes--;
|
||||
WARN_ON_ONCE(writes < 0);
|
||||
if (writes > 0)
|
||||
return -EAGAIN;
|
||||
spin_lock(&fp->fi_lock);
|
||||
list_for_each_entry(co, &fp->fi_clnt_odstate, co_perfile) {
|
||||
if (co->co_client != clp) {
|
||||
spin_unlock(&fp->fi_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
spin_unlock(&fp->fi_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nfs4_delegation *
|
||||
nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
|
||||
struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate)
|
||||
@@ -4959,9 +4985,12 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
|
||||
|
||||
nf = find_readable_file(fp);
|
||||
if (!nf) {
|
||||
/* We should always have a readable file here */
|
||||
WARN_ON_ONCE(1);
|
||||
return ERR_PTR(-EBADF);
|
||||
/*
|
||||
* We probably could attempt another open and get a read
|
||||
* delegation, but for now, don't bother until the
|
||||
* client actually sends us one.
|
||||
*/
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
spin_lock(&state_lock);
|
||||
spin_lock(&fp->fi_lock);
|
||||
@@ -4991,11 +5020,19 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
|
||||
if (!fl)
|
||||
goto out_clnt_odstate;
|
||||
|
||||
status = nfsd4_check_conflicting_opens(clp, fp);
|
||||
if (status) {
|
||||
locks_free_lock(fl);
|
||||
goto out_clnt_odstate;
|
||||
}
|
||||
status = vfs_setlease(fp->fi_deleg_file->nf_file, fl->fl_type, &fl, NULL);
|
||||
if (fl)
|
||||
locks_free_lock(fl);
|
||||
if (status)
|
||||
goto out_clnt_odstate;
|
||||
status = nfsd4_check_conflicting_opens(clp, fp);
|
||||
if (status)
|
||||
goto out_clnt_odstate;
|
||||
|
||||
spin_lock(&state_lock);
|
||||
spin_lock(&fp->fi_lock);
|
||||
@@ -5077,17 +5114,6 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
|
||||
goto out_no_deleg;
|
||||
if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
|
||||
goto out_no_deleg;
|
||||
/*
|
||||
* Also, if the file was opened for write or
|
||||
* create, there's a good chance the client's
|
||||
* about to write to it, resulting in an
|
||||
* immediate recall (since we don't support
|
||||
* write delegations):
|
||||
*/
|
||||
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
|
||||
goto out_no_deleg;
|
||||
if (open->op_create == NFS4_OPEN_CREATE)
|
||||
goto out_no_deleg;
|
||||
break;
|
||||
default:
|
||||
goto out_no_deleg;
|
||||
|
新增問題並參考
封鎖使用者