7 6=42131 5 3=古美路1582号 4 6=24102 2 7=?

CAS no CAS Number ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
按产品CAS号首数字顺序排列:->->->->->->->->
英文名称中文名称CASMF
C210H314N56O57S1
C27H58ClNO4
C21H40N8O6
(C12H17O19S3)n
C4H6N2O3R2.(C7H9N2O2R)n
C14H22NNaO11
R(OCH2CH2CH2CH2)nOR,R=-CONHC6H3(NCO)CH3
产品名称:
需求量最少填写一个,最多可以填写两个
收货地址:
发票类型:
增值税专用发票(16%)
增值税普通发票(普票)
不公开我的联系方式
询单已收到,专属客服稍后会联系您!
您还可以登录后台“”
及时查看报价
及时查看报价
或者进入chemicalbookfs/nfs/nfs4state.c
Client-side XDR for NFSv4.
Copyright (c) 2002 The Regents of the University of Michigan.
All rights reserved.
Kendrick Smith &kmsmith@umich.edu&
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Implementation of the NFSv4 state model.
For the time being,
* this is minimal, but will be made much more complex in a
* subsequent patch.
#include &linux/kernel.h&
#include &linux/slab.h&
#include &linux/fs.h&
#include &linux/nfs_fs.h&
#include &linux/kthread.h&
#include &linux/module.h&
#include &linux/random.h&
#include &linux/ratelimit.h&
#include &linux/workqueue.h&
#include &linux/bitops.h&
#include &linux/jiffies.h&
#include &linux/sunrpc/clnt.h&
#include &nfs4_fs.h&
#include &callback.h&
#include &delegation.h&
#include &internal.h&
#include &nfs4idmap.h&
#include &nfs4session.h&
#include &pnfs.h&
#include &netns.h&
{ .data = { 0 } },
/* Funky initialiser keeps older gcc versions happy */
.data = { 0xff, 0xff, 0xff, 0xff, 0 },
static (nfs_clid_init_mutex);
int (struct
*clp, struct
.clientid = clp-&cl_clientid,
.confirm = clp-&cl_confirm,
unsigned short port;
int status;
*nn = (clp-&cl_net, );
if ((, &clp-&))
goto do_confirm;
port = nn-&;
if (clp-&cl_addr.ss_family == )
port = nn-&;
status = (clp, , port, , &clid);
if (status != 0)
clp-&cl_clientid = clid.clientid;
clp-&cl_confirm = clid.confirm;
(, &clp-&);
do_confirm:
status = (clp, &clid, );
if (status != 0)
(, &clp-&);
return status;
* nfs40_discover_server_trunking - Detect server IP address trunking (mv0)
* @clp: nfs_client under test
* @result: OUT: found nfs_client, or clp
* @cred: credential to use for trunking test
* Returns zero, a negative errno, or a negative NFS4ERR status.
* If zero is returned, an nfs_client pointer is planted in
* &result&.
* Note: The returned client may not yet be marked ready.
int (struct
.clientid = clp-&cl_clientid,
.confirm = clp-&cl_confirm,
*nn = (clp-&cl_net, );
unsigned short port;
int status;
port = nn-&;
if (clp-&cl_addr.ss_family == )
port = nn-&;
status = (clp, , port, , &clid);
if (status != 0)
clp-&cl_clientid = clid.clientid;
clp-&cl_confirm = clid.confirm;
status = (clp, result, );
if (status == 0) {
/* Sustain the lease, even if it's empty.
If the clientid4
* goes stale it's of no use for trunking discovery. */
(*result);
return status;
if (clp-&cl_machine_cred != NULL)
= (clp-&cl_machine_cred);
static void (struct
= clp-&cl_machine_cred;
clp-&cl_machine_cred = ;
if ( != NULL)
static struct
for ( = (&server-&state_owners);
= (, struct , so_server_node);
if ((&-&so_states))
= (-&so_cred);
* nfs4_get_renew_cred_locked - Acquire credential for a renew operation
* @clp: client state handle
* Returns an rpc_cred with reference count bumped, or NULL.
* Caller must hold clp-&cl_lock.
/* Use machine credentials if available */
if ( != NULL)
(server, &clp-&cl_superblocks, client_link) {
= (server);
if ( != NULL)
static void (struct
if ((, &tbl-&slot_tbl_state)) {
(&tbl-&slot_tbl_lock);
(&tbl-&slot_tbl_lock);
static void (struct
*ses = clp-&cl_session;
if (clp-&cl_slot_tbl) {
(clp-&cl_slot_tbl);
if (ses != NULL) {
(&ses-&bc_slot_table);
(&ses-&fc_slot_table);
static int (struct
(, &tbl-&slot_tbl_state);
(&tbl-&slot_tbl_lock);
if (tbl-&highest_used_slotid != ) {
(&tbl-&slot_tbl_lock);
return (&tbl-&);
(&tbl-&slot_tbl_lock);
static int (struct
*ses = clp-&cl_session;
int ret = 0;
if (clp-&cl_slot_tbl)
return (clp-&cl_slot_tbl);
/* back channel */
ret = (&ses-&bc_slot_table);
return ret;
/* fore channel */
return (&ses-&fc_slot_table);
#if (CONFIG_NFS_V4_1)
static int (struct
int status;
unsigned long ;
if (!(, &clp-&cl_res_state)) {
status = (clp, &fsinfo);
if (status == 0) {
(clp, fsinfo. * , );
return status;
static void (struct
(, &clp-&);
(, &clp-&);
/* create_session negotiated new slot table */
(, &clp-&);
int (struct
*clp, struct
int status;
if ((, &clp-&))
goto do_confirm;
status = (clp, );
if (status != 0)
(, &clp-&);
do_confirm:
status = (clp, );
if (status != 0)
return status;
* nfs41_discover_server_trunking - Detect server IP address trunking (mv1)
* @clp: nfs_client under test
* @result: OUT: found nfs_client, or clp
* @cred: credential to use for trunking test
* Returns NFS4_OK, a negative errno, or a negative NFS4ERR status.
* If NFS4_OK is returned, an nfs_client pointer is planted in
* &result&.
* Note: The returned client may not yet be marked ready.
int (struct
int status;
status = (clp, );
if (status != )
return status;
status = (clp, result, );
if (status & 0)
return status;
if (clp != *result)
* Purge state if the client id was established in a prior
* instance and the client id could not have arrived on the
* server via Transparent State Migration.
if (clp-&cl_exchange_flags & ) {
if (!(, &clp-&cl_flags))
(, &clp-&);
(, &clp-&);
status = (clp);
if (status & 0)
return status;
#endif /* CONFIG_NFS_V4_1 */
* nfs4_get_clid_cred - Acquire credential for a setclientid operation
* @clp: client state handle
* Returns an rpc_cred with reference count bumped, or NULL.
static struct
*server, struct
**p = &server-&state_owners.,
while (*p != NULL) {
= (, struct , so_server_node);
if ( & -&so_cred)
p = &-&rb_left;
else if ( & -&so_cred)
p = &-&rb_right;
if (!(&-&so_lru))
(&-&so_lru);
(&-&so_count);
return NULL;
static struct
*server = -&so_server;
**p = &server-&state_owners.,
while (*p != NULL) {
= (, struct , so_server_node);
if (-&so_cred & -&so_cred)
p = &-&rb_left;
else if (-&so_cred & -&so_cred)
p = &-&rb_right;
if (!(&-&so_lru))
(&-&so_lru);
(&-&so_count);
(&-&so_server_node, , p);
(&-&so_server_node, &server-&state_owners);
static void
*server = -&so_server;
if (!(&-&so_server_node))
(&-&so_server_node, &server-&state_owners);
static void
-&create_time = ();
-&flags = 0;
(&-&lock);
(&-&list);
(&-&, &Seqid_waitqueue&);
static void
* nfs4_alloc_state_owner(): this is called on the OPEN or CREATE path to
* create a new state_owner.
static struct
gfp_flags)
= (sizeof(*), gfp_flags);
return NULL;
-&so_seqid.owner_id = (&server-&openowner_id, 0, 0,
gfp_flags);
if (-&so_seqid.owner_id & 0) {
return NULL;
-&so_server = server;
-&so_cred = ();
(&-&so_lock);
(&-&so_states);
(&-&so_seqid);
(&-&so_count, 1);
(&-&so_lru);
(&-&so_reclaim_seqcount);
(&-&so_delegreturn_mutex);
static void
/* This state_owner is no longer usable, but must
* remain in place so that state recovery can find it
* and the opens associated with it.
* It may also be used for new 'open' request to
* return a delegation to the server.
* So update the 'create_time' so that it looks like
* a new state_owner.
This will cause the server to
* request an OPEN_CONFIRM to start a new sequence.
-&so_seqid.create_time = ();
static void (struct
(&-&so_seqid);
(-&so_cred);
(&-&so_server-&openowner_id, -&so_seqid.owner_id);
static void (struct
*clp = server-&;
unsigned long time_min, time_max;
time_max = ;
time_min = (long)time_max - (long)clp-&cl_lease_time;
(, tmp, &server-&state_owners_lru, so_lru) {
/* NB: LRU is sorted so that oldest is at the head */
if ((-&so_expires, time_min, time_max))
(&-&so_lru, &doomed);
(, tmp, &doomed, so_lru) {
(&-&so_lru);
* nfs4_get_state_owner - Look up a state owner given a credential
* @server: nfs_server to search
* @cred: RPC credential to match
* Returns a pointer to an instantiated nfs4_state_owner struct, or NULL.
gfp_flags)
*clp = server-&;
= (server, );
if ( != NULL)
= (server, , gfp_flags);
if ( == NULL)
* nfs4_put_state_owner - Release a nfs4_state_owner
* @sp: state owner data to release
* Note that we keep released state owners on an LRU
* This caches valid state owners so that they can be
* reused, to avoid the OPEN_CONFIRM on minor version 0.
* It also pins the uniquifier of dropped state owners for
* a while, to ensure that those state owner names are
* never reused.
void (struct
*server = -&so_server;
*clp = server-&;
if (!(&-&so_count, &clp-&))
-&so_expires = ;
(&-&so_lru, &server-&state_owners_lru);
* nfs4_purge_state_owners - Release all cached state owners
* @server: nfs_server with cached state owners to release
* Called at umount time.
Remaining state owners will be on
* the LRU with ref count of zero.
void (struct
*clp = server-&;
(, tmp, &server-&state_owners_lru, so_lru) {
(&-&so_lru, &doomed);
(, tmp, &doomed, so_lru) {
(&-&so_lru);
static struct
state = (sizeof(*state), );
if (!state)
return NULL;
(&state-&count, 1);
(&state-&lock_states);
(&state-&);
(&state-&seqlock);
(&state-&waitq);
return state;
if (state-&state == )
/* NB! List reordering - see the reclaim code for why.
if (( & ) != (state-&state & )) {
(&state-&open_states, &state-&-&so_states);
(&state-&open_states, &state-&-&so_states);
state-&state = ;
static struct
(struct inode *inode, struct
*nfsi = (inode);
(state, &nfsi-&open_states, inode_states) {
if (state-& != )
if (!(state))
if ((&state-&count))
return state;
return NULL;
static void
(struct inode *inode, struct
*state, *;
*nfsi = (inode);
(&inode-&i_lock);
state = (inode, );
(&inode-&i_lock);
if (state)
(&-&so_lock);
(&inode-&i_lock);
state = (inode, );
if (state == NULL &&
!= NULL) {
state-& = ;
(&-&so_count);
(&state-&inode_states, &nfsi-&open_states);
state-&inode = inode;
(&inode-&i_lock);
/* Note: The reclaim code dictates that we add stateless
* and read-only stateids to the end of the list */
(&state-&open_states, &-&so_states);
(&-&so_lock);
(&inode-&i_lock);
(&-&so_lock);
return state;
void (struct
struct inode *inode = state-&inode;
* = state-&;
if (!(&state-&count, &-&so_lock))
(&inode-&i_lock);
(&state-&inode_states);
(&state-&open_states);
(&inode-&i_lock);
(&-&so_lock);
* Close the current file.
static void (struct
gfp_mask, int )
* = state-&;
int call_close = 0;
(&-&so_count);
/* Protect against nfs4_find_state() */
(&-&so_lock);
switch ( & ( | )) {
state-&n_rdonly--;
state-&n_wronly--;
state-&n_rdwr--;
newstate = |;
if (state-&n_rdwr == 0) {
if (state-&n_rdonly == 0) {
newstate &= ~;
call_close |= (, &state-&flags);
call_close |= (, &state-&flags);
if (state-&n_wronly == 0) {
newstate &= ~;
call_close |= (, &state-&flags);
call_close |= (, &state-&flags);
if (newstate == 0)
(, &state-&flags);
(state, newstate);
(&-&so_lock);
if (!call_close) {
(state, gfp_mask, );
void (struct
(state, , , 0);
void (struct
(state, , , 1);
* Search the state-&lock_states for an existing lock_owner
* that is compatible with either of the given owners.
* If the second is non-zero, then the first refers to a Posix-lock
* owner (current-&files) and the second refers to a flock/OFD
* owner (struct file*).
In that case, prefer a match for the first
* If both sorts of locks are held on the one file we cannot know
* which stateid was intended to be used, so a &correct& choice cannot
* be made.
Failing that, a &consistent& choice is preferable.
* consistent choice we make is to prefer the first owner, that of a
* Posix lock.
static struct
fl_owner2)
*, *ret = NULL;
(, &state-&lock_states, ls_locks) {
if (-&ls_owner == fl_owner) {
if (-&ls_owner == fl_owner2)
return ret;
* Return a compatible lock_state. If no initialized lock_state structure
* exists, return an uninitialized one.
static struct
*server = state-&-&so_server;
lsp = (sizeof(*lsp), );
if (lsp == NULL)
return NULL;
(&lsp-&ls_seqid);
(&lsp-&, 1);
lsp-&ls_state = state;
lsp-&ls_owner = fl_owner;
lsp-&ls_seqid.owner_id = (&server-&lockowner_id, 0, 0, );
if (lsp-&ls_seqid.owner_id & 0)
goto out_free;
(&lsp-&ls_locks);
return lsp;
return NULL;
void (struct
*server, struct
(&server-&lockowner_id, lsp-&ls_seqid.owner_id);
(&lsp-&ls_seqid);
* Return a compatible lock_state. If no initialized lock_state structure
* exists, return an uninitialized one.
static struct
*lsp, * = NULL;
(&state-&);
lsp = (state, , NULL);
if (lsp != NULL)
if ( != NULL) {
(&-&ls_locks, &state-&lock_states);
(, &state-&flags);
(&state-&);
= (state, );
if ( == NULL)
return NULL;
(&state-&);
if ( != NULL)
(state-&-&so_server, );
return lsp;
* Release reference to lock_state, and free it if we see that
* it is no longer in use
void (struct
if (lsp == NULL)
state = lsp-&ls_state;
if (!(&lsp-&, &state-&))
(&lsp-&ls_locks);
if ((&state-&lock_states))
(, &state-&flags);
(&state-&);
server = state-&-&so_server;
if ((, &lsp-&ls_flags)) {
*clp = server-&;
clp-&cl_mvops-&free_lock_state(server, lsp);
(server, lsp);
static void (struct
*lsp = -&fl_u.nfs4_fl.;
-&fl_u.nfs4_fl. = lsp;
static void (struct
(fl-&fl_u.nfs4_fl.);
static const struct
.fl_copy_lock = ,
.fl_release_private = ,
int (struct
*state, struct
if (fl-&fl_ops != NULL)
lsp = (state, fl-&fl_owner);
if (lsp == NULL)
fl-&fl_u.nfs4_fl. = lsp;
fl-&fl_ops = &;
static int ( *,
const struct
fl_owner, fl_flock_owner;
int ret = -;
if (l_ctx == NULL)
if ((, &state-&flags) == 0)
fl_owner = l_ctx-&;
fl_flock_owner = l_ctx-&open_context-&flock_owner;
(&state-&);
lsp = (state, fl_owner, fl_flock_owner);
if (lsp && (, &lsp-&ls_flags))
else if (lsp != NULL && (, &lsp-&ls_flags) != 0) {
(, &lsp-&ls_stateid);
(&state-&);
return ret;
bool ( *, struct
ret = false;
= (&state-&seqlock);
if ((state, )) {
-&seqid = state-&open_stateid.seqid;
ret = true;
} while ((&state-&seqlock, ));
return ret;
bool ( *, struct
ret = false;
= (&state-&seqlock);
if ((, &state-&flags)) {
= &state-&open_stateid;
ret = true;
} while ((&state-&seqlock, ));
return ret;
* Byte-range lock aware utility to initialize the stateid of read/write
* requests.
int (struct
, const struct
if (!(state))
if ( != NULL)
ret = (, state, l_ctx);
if (ret == -)
/* A lost lock - don't even consider delegations */
/* returns true if delegation stateid found and copied */
if ((state-&inode, , , )) {
if (ret != -)
/* nfs4_copy_delegation_stateid() didn't over-write
* dst, so it still has the lock stateid which we now
* choose to use.
(, state);
if ((state-&inode, ))
-&seqid = 0;
return ret;
= (sizeof(*), gfp_mask);
if ( == NULL)
return (-);
(&-&list);
-& = NULL;
void (struct
if (seqid == NULL || (&seqid-&list))
= seqid-&;
(&-&lock);
(&seqid-&list);
if (!(&-&list)) {
next = (&-&list,
struct , list);
(&-&, next-&);
(&-&lock);
void (struct
* Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
* failed with a seqid incrementing error -
* see comments nfs4.h:seqid_mutating_error()
static void (int status, struct
switch (status) {
if (seqid-&-&flags & )
(&NFS: v4 server returned a bad&
& sequence-id error on an&
& unconfirmed sequence %p!\n&,
/* Non-seqid mutating errors */
* Note: no locking needed as we are guaranteed to be first
* on the sequence list
seqid-&-&++;
void (int status, struct
if (seqid == NULL)
= (seqid-&, struct , so_seqid);
if (status == -)
if (!(-&so_server-&))
(status, seqid);
* Increment the seqid if the LOCK/LOCKU succeeded, or
* failed with a seqid incrementing error -
* see comments nfs4.h:seqid_mutating_error()
void (int status, struct
if (seqid != NULL)
(status, seqid);
int (struct
*seqid, struct
int status = 0;
if (seqid == NULL)
= seqid-&;
(&-&lock);
seqid-& = ;
if ((&seqid-&list))
(&seqid-&list, &-&list);
if ((&-&list, struct , list) == seqid)
goto unlock;
(&-&, , NULL);
status = -;
(&-&lock);
return status;
static int (void *);
static void (struct
(, &clp-&);
(&clp-&, );
(&clp-&cl_rpcwaitq);
* Schedule the nfs_client asynchronous state management routine
void (struct
char buf[ + sizeof(&-manager&) + 1];
if ((, &clp-&) != 0)
(&clp-&cl_count);
/* The rcu_read_lock() is not strictly necessary, as the state
* manager is the only thread that ever changes the rpc_xprt
* after it's initialized.
At this point, we're single threaded. */
(buf, sizeof(buf), &%s-manager&,
(clp-&cl_rpcclient, ));
= (, clp, &%s&, buf);
( &%s: kthread_run: %ld\n&,
__func__, ());
* Schedule a lease recovery attempt
void (struct
if (!(, &clp-&))
(, &clp-&);
(&%s: scheduling lease recovery for server %s\n&, __func__,
clp-&cl_hostname);
* nfs4_schedule_migration_recovery - trigger migration recovery
* @server: FSID that is migrating
* Returns zero if recovery has started, otherwise a negative NFS4ERR
* value is returned.
int (const struct
*clp = server-&;
if (server-&fh_expire_type != ) {
(&NFS: volatile file handles not supported (server %s)\n&,
clp-&cl_hostname);
if ((, &server-&mig_status))
(&%s: scheduling migration recovery for (%llx:%llx) on %s\n&,
(unsigned long long)server-&fsid.,
(unsigned long long)server-&fsid.,
clp-&cl_hostname);
*)server)-&mig_status);
(, &clp-&);
* nfs4_schedule_lease_moved_recovery - start lease-moved recovery
* @clp: server to check for moved leases
void (struct
(&%s: scheduling lease-moved recovery for client ID %llx on %s\n&,
__func__, clp-&cl_clientid, clp-&cl_hostname);
(, &clp-&);
int (struct
(&clp-&cl_count);
res = (&clp-&, ,
if (clp-&cl_cons_state & 0)
res = clp-&cl_cons_state;
return res;
int (struct
unsigned int ;
!= 0; --) {
ret = (clp);
if (ret != 0)
if (!(, &clp-&) &&
!(,&clp-&))
return ret;
* nfs40_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN
* @clp: client to process
* Set the NFS4CLNT_LEASE_EXPIRED state in order to force a
* resend of the SETCLIENTID and hence re-establish the
* callback channel. Then return all existing delegations.
static void (struct
(, &clp-&);
(&%s: handling CB_PATHDOWN recovery for server %s\n&, __func__,
clp-&cl_hostname);
void (struct
static int (struct
*clp, struct
if (!(state))
(, &state-&flags);
/* Don't recover state that expired before the reboot */
if ((, &state-&flags)) {
(, &state-&flags);
(, &state-&-&so_flags);
(, &clp-&);
int (struct
*clp, struct
if (!(state))
(, &state-&flags);
(, &state-&flags);
(, &state-&-&so_flags);
(, &clp-&);
int (const struct
*server, struct
*clp = server-&;
if (!(clp, state))
(&%s: scheduling stateid recovery for server %s\n&, __func__,
clp-&cl_hostname);
static struct
(, &state-&lock_states, ls_locks) {
if (!(, &-&ls_flags))
if ((&-&ls_stateid, stateid))
return NULL;
static bool (struct
if ((, &state-&flags)) {
(&state-&);
if ((state, stateid))
(&state-&);
void (struct inode *inode,
*clp = (inode)-&;
*nfsi = (inode);
(&inode-&i_lock);
(ctx, &nfsi-&, list) {
state = ctx-&state;
if (state == NULL)
if ((&state-&stateid, stateid) &&
(clp, state)) {
if ((&state-&open_stateid, stateid) &&
(clp, state)) {
if ((state, stateid) &&
(clp, state))
(&inode-&i_lock);
(inode, stateid);
static void (struct
struct inode *inode = state-&inode;
*nfsi = (inode);
(&inode-&i_lock);
(ctx, &nfsi-&, list) {
if (ctx-&state != state)
(, &ctx-&flags);
(&inode-&i_lock);
static void (struct
*state, int error)
(, &state-&flags);
static int (struct
*state, const struct
struct inode *inode = state-&inode;
*nfsi = (inode);
int status = 0;
*flctx = inode-&i_flctx;
if (flctx == NULL)
list = &flctx-&flc_posix;
/* Guard against delegation returns and new lock/unlock calls */
(&nfsi-&rwsem);
(&flctx-&flc_lock);
(fl, list, fl_list) {
if ((fl-&fl_file)-&state != state)
(&flctx-&flc_lock);
status = ops-&recover_lock(state, fl);
switch (status) {
(&NFS: %s: unhandled error %d\n&,
__func__, status);
lsp = fl-&fl_u.nfs4_fl.;
(, &lsp-&ls_flags);
status = 0;
(&flctx-&flc_lock);
if (list == &flctx-&flc_posix) {
list = &flctx-&flc_flock;
(&flctx-&flc_lock);
(&nfsi-&rwsem);
return status;
static int (struct
*, const struct
int status = 0;
/* Note: we rely on the sp-&so_states list being ordered
* so that we always reclaim open(O_RDWR) and/or open(O_WRITE)
* states first.
* This is needed to ensure that the server won't give us any
* read delegations that we have to return if, say, we are
* recovering after a network partition or a reboot from a
* server that doesn't support a grace period.
(&-&so_lock);
(&-&so_reclaim_seqcount);
(state, &-&so_states, open_states) {
if (!(ops-&state_flag_bit, &state-&flags))
if (!(state))
if (state-&state == 0)
(&state-&count);
(&-&so_lock);
status = ops-&recover_open(, state);
if (status &= 0) {
status = (state, ops);
if (status &= 0) {
if (!(, &state-&flags)) {
(&state-&);
(lock, &state-&lock_states, ls_locks) {
if (!(, &lock-&ls_flags))
&%s: Lock reclaim &
&failed!\n&, __func__);
(&state-&);
&state-&flags);
(&-&so_lock);
switch (status) {
( &NFS: %s: unhandled error %d\n&,
__func__, status);
/* Open state on this file cannot be recovered */
(state, status);
(-&so_server-&, state);
(-&so_server-&, state);
goto out_err;
(&-&so_lock);
(&-&so_reclaim_seqcount);
(&-&so_lock);
(&-&so_lock);
(&-&so_reclaim_seqcount);
(&-&so_lock);
return status;
static void (struct
(, &state-&flags);
(, &state-&flags);
(, &state-&flags);
(, &state-&flags);
(&state-&);
(lock, &state-&lock_states, ls_locks) {
lock-&ls_seqid.flags = 0;
(, &lock-&ls_flags);
(&state-&);
static void (struct
int (*mark_reclaim)(struct
*clp, struct
*clp = server-&;
for ( = (&server-&state_owners);
= (, struct , so_server_node);
-&so_seqid.flags = 0;
(&-&so_lock);
(state, &-&so_states, open_states) {
if (mark_reclaim(clp, state))
(&-&so_lock);
static void (struct
int (*mark_reclaim)(struct
*clp, struct
(server, &clp-&cl_superblocks, client_link)
(server, mark_reclaim);
static void (struct
/* Mark all delegations for reclaim */
static int (struct
const struct
/* Notify the server we're done reclaiming our state */
if (ops-&reclaim_complete)
return ops-&reclaim_complete(clp, );
static void (struct
*clp = server-&;
for ( = (&server-&state_owners);
= (, struct , so_server_node);
(&-&so_lock);
(state, &-&so_states, open_states) {
&state-&flags))
(clp, state);
(&-&so_lock);
static int (struct
if (!(, &clp-&))
(server, &clp-&cl_superblocks, client_link)
static void (struct
const struct
if (!(clp))
ops = clp-&cl_mvops-&reboot_recovery_ops;
err = (clp, ops, );
if (err == -)
(, &clp-&);
static void (struct
static int (struct
*clp, int error)
switch (error) {
(, &clp-&);
(, &clp-&);
(, &clp-&);
/* Zero session reset errors */
(, &clp-&);
(&%s: failed to handle error %d for server %s\n&,
__func__, error, clp-&cl_hostname);
return error;
(&%s: handled error %d for server %s\n&, __func__, error,
clp-&cl_hostname);
static int (struct
*clp, const struct
int status = 0;
(server, &clp-&cl_superblocks, client_link) {
for ( = (&server-&state_owners);
struct , so_server_node);
if (!(ops-&owner_flag_bit,
&-&so_flags))
if (!(&-&so_count))
status = (, ops);
if (status & 0) {
(ops-&owner_flag_bit, &-&so_flags);
status = (clp, status);
return (status != 0) ? status : -;
static int (struct
const struct
clp-&cl_mvops-&state_renewal_ops;
int status;
/* Is the client already known to have an expired lease? */
if ((, &clp-&))
= ops-&get_state_renewal_cred_locked(clp);
if ( == NULL) {
status = -;
if ( == NULL)
status = ops-&(clp, );
if (status == -) {
(, &clp-&);
return (clp, status);
/* Set NFS4CLNT_LEASE_EXPIRED and reclaim reboot state for all v4.0 errors
* and for recoverable errors on EXCHANGE_ID for v4.1
static int (struct
*clp, int status)
switch (status) {
if ((, &clp-&))
/* Lease confirmation error: retry after purging the lease */
(, &clp-&);
(, &clp-&);
(&NFS: Server %s reports our clientid is in use\n&,
clp-&cl_hostname);
(, &clp-&);
if (clp-&cl_cons_state == )
(&%s: exit with error %d for server %s\n&,
__func__, -, clp-&cl_hostname);
case -: /* FixMe: implement recovery
* in nfs4_exchange_id */
(&%s: exit with error %d for server %s\n&, __func__,
status, clp-&cl_hostname);
return status;
(, &clp-&);
(&%s: handled error %d for server %s\n&, __func__, status,
clp-&cl_hostname);
static int (struct
const struct
clp-&cl_mvops-&reboot_recovery_ops;
int status;
if ( == NULL)
status = ops-&establish_clid(clp, );
if (status != 0)
return status;
* Returns zero or a negative errno.
NFS4ERR values are converted
* to local errno values.
static int (struct
int status;
status = (clp);
if (status & 0)
return (clp, status);
if ((, &clp-&))
if (!(, &clp-&))
(, &clp-&);
(, &clp-&);
(, &clp-&);
static int (struct
int status;
status = (clp);
if (status & 0)
return (clp, status);
(, &clp-&);
(, &clp-&);
* Try remote migration of one FSID from a source server to a
* destination server.
The source server provides a list of
* potential destinations.
* Returns zero or a negative NFS4ERR status code.
static int (struct
*server, struct
*clp = server-&;
*locations = NULL;
struct inode *inode;
struct page *page;
int status, result;
(&--& %s: FSID %llx:%llx on \&%s\&\n&, __func__,
(unsigned long long)server-&fsid.,
(unsigned long long)server-&fsid.,
clp-&cl_hostname);
result = 0;
page = ();
locations = (sizeof(struct ), );
if (page == NULL || locations == NULL) {
(&&-- %s: no memory\n&, __func__);
inode = (server-&super-&s_root);
result = (inode, locations, page, );
if (result) {
(&&-- %s: failed to retrieve fs_locations: %d\n&,
__func__, result);
result = -;
if (!(locations-&fattr.valid & )) {
(&&-- %s: No fs_locations data, migration skipped\n&,
__func__);
status = (server, locations);
if (status != 0) {
(&&-- %s: failed to replace transport: %d\n&,
__func__, status);
result = 0;
(&&-- %s: migration succeeded\n&, __func__);
if (page != NULL)
(locations);
if (result) {
(&NFS: migration recovery failed (server %s)\n&,
clp-&cl_hostname);
(, &server-&mig_status);
return result;
* Returns zero or a negative NFS4ERR status code.
static int (struct
const struct
clp-&cl_mvops-&state_renewal_ops;
(&%s: migration reported on \&%s\&\n&, __func__,
clp-&cl_hostname);
= ops-&get_state_renewal_cred_locked(clp);
if ( == NULL)
clp-&cl_mig_gen++;
(server, &clp-&cl_superblocks, client_link) {
int status;
if (server-&mig_gen == clp-&cl_mig_gen)
server-&mig_gen = clp-&cl_mig_gen;
&server-&mig_status))
status = (server, );
if (status & 0) {
return status;
* Test each nfs_server on the clp's cl_superblocks list to see
* if it's moved to another server.
Stop when the server no longer
* returns NFS4ERR_LEASE_MOVED.
static int (struct
const struct
clp-&cl_mvops-&state_renewal_ops;
(&%s: lease moved reported on \&%s\&\n&, __func__,
clp-&cl_hostname);
= ops-&get_state_renewal_cred_locked(clp);
if ( == NULL)
clp-&cl_mig_gen++;
(server, &clp-&cl_superblocks, client_link) {
struct inode *inode;
int status;
if (server-&mig_gen == clp-&cl_mig_gen)
server-&mig_gen = clp-&cl_mig_gen;
inode = (server-&super-&s_root);
status = (inode, );
if (status != -)
goto ; /* wasn't this one */
if ((server, ) == -)
goto ; /* there are more */
* nfs4_discover_server_trunking - Detect server IP address trunking
* @clp: nfs_client under test
* @result: OUT: found nfs_client, or clp
* Returns zero or a negative errno.
If zero is returned,
* an nfs_client pointer is planted in &result&.
* Note: since we are invoked in process context, and
* not from inside the state manager, we cannot use
* nfs4_handle_reclaim_lease_error().
int (struct
const struct
clp-&cl_mvops-&reboot_recovery_ops;
int i, status;
(&NFS: %s: testing '%s'\n&, __func__, clp-&cl_hostname);
clnt = clp-&cl_rpcclient;
(&nfs_clid_init_mutex);
if ( == NULL)
goto out_unlock;
status = ops-&detect_trunking(clp, result, );
switch (status) {
if (clnt-&cl_softrtry)
(&NFS: %s after status %d, retrying\n&,
__func__, status);
if (i++ == 0) {
if (clnt-&cl_auth-&au_flavor == )
/* No point in retrying if we already used RPC_AUTH_UNIX */
if (clnt-&cl_auth-&au_flavor == ) {
status = -;
clnt = (clnt, );
if ((clnt)) {
status = (clnt);
/* Note: this is safe because we haven't yet marked the
* client as ready, so we are the only user of
* clp-&cl_rpcclient
clnt = (&clp-&cl_rpcclient, clnt);
clnt = clp-&cl_rpcclient;
status = -;
case -: /* FixMe: implement recovery
* in nfs4_exchange_id */
status = -;
(&NFS: %s unhandled error %d. Exiting with error EIO\n&,
__func__, status);
status = -;
out_unlock:
(&nfs_clid_init_mutex);
(&NFS: %s: status = %d\n&, __func__, status);
return status;
#ifdef CONFIG_NFS_V4_1
void (struct
*, int err)
*clp = -&clp;
switch (err) {
(, &clp-&);
(, &clp-&);
void (struct
/* Use CHECK_LEASE to ping the server with a SEQUENCE */
(, &clp-&);
static void (struct
if ((, &clp-&) == 0) {
(, &clp-&);
(, &clp-&);
(&%s: scheduling reset of all state for server %s!\n&,
__func__, clp-&cl_hostname);
static void (struct
if ((, &clp-&) == 0) {
(&%s: server %s rebooted!\n&, __func__,
clp-&cl_hostname);
static void (struct
(&%s: state revoked on server %s\n&, __func__, clp-&cl_hostname);
static void (struct
(&%s: state revoked on server %s\n&, __func__, clp-&cl_hostname);
static void (struct
/* FIXME: For now, we destroy all layouts. */
/* FIXME: For now, we test all delegations+open state+locks. */
(&%s: Recallable state revoked on server %s!\n&, __func__,
clp-&cl_hostname);
static void (struct
(, &clp-&);
(&%s: server %s declared a backchannel fault\n&, __func__,
clp-&cl_hostname);
static void (struct
&clp-&) == 0)
void (struct
*clp, u32 flags,
bool recovery)
if (!flags)
(&%s: \&%s\& (client ID %llx) flags=0x%08x\n&,
__func__, clp-&cl_hostname, clp-&cl_clientid, flags);
* If we're called from the state manager thread, then assume we're
* already handling the RECLAIM_NEEDED and/or STATE_REVOKED.
* Those flags are expected to remain set until we're done
* recovering (see RFC5661, section 18.46.3).
if (recovery)
goto out_recovery;
if (flags & )
if (flags & ())
if (flags & ( |
if (flags & )
if (flags & )
out_recovery:
if (flags & )
else if (flags & ( |
static int (struct
int status;
if (!(clp))
status = (clp-&cl_session, );
switch (status) {
(, &clp-&);
status = 0;
status = (clp, status);
memset(clp-&cl_session-&sess_id.data, 0, );
status = (clp, );
if (status) {
(&%s: session reset failed with status %d for server %s!\n&,
__func__, status, clp-&cl_hostname);
status = (clp, status);
(&%s: session reset was successful for server %s!\n&,
__func__, clp-&cl_hostname);
return status;
static int (struct
if (!(clp))
ret = (clp, );
(, &clp-&);
switch (ret) {
(&%s: bind_conn_to_session was successful for server %s!\n&,
__func__, clp-&cl_hostname);
(, &clp-&);
return (clp, ret);
#else /* CONFIG_NFS_V4_1 */
static int (struct
*clp) { return 0; }
static int (struct
#endif /* CONFIG_NFS_V4_1 */
static void (struct
int status = 0;
const char * = &&, *section_sep = &&;
/* Ensure exclusive access to NFSv4 state */
if ((, &clp-&)) {
= &purge state&;
status = (clp);
if (status & 0)
goto out_error;
if ((, &clp-&)) {
= &lease expired&;
/* We're going to have to re-establish a clientid */
status = (clp);
if (status & 0)
goto out_error;
/* Initialize or reset the session */
if ((, &clp-&)) {
= &reset session&;
status = (clp);
if ((, &clp-&))
if (status & 0)
goto out_error;
/* Send BIND_CONN_TO_SESSION */
&clp-&)) {
= &bind conn to session&;
status = (clp);
if (status & 0)
goto out_error;
if ((, &clp-&)) {
= &check lease&;
status = (clp);
if (status & 0)
goto out_error;
if ((, &clp-&)) {
= &migration&;
status = (clp);
if (status & 0)
goto out_error;
if ((, &clp-&)) {
= &lease moved&;
status = (clp);
if (status & 0)
goto out_error;
/* First recover reboot state... */
if ((, &clp-&)) {
= &reclaim reboot&;
status = (clp,
clp-&cl_mvops-&reboot_recovery_ops);
if (status == -)
if (status & 0)
goto out_error;
/* Detect expired delegations... */
if ((, &clp-&)) {
= &detect expired delegations&;
/* Now recover expired state... */
if ((, &clp-&)) {
= &reclaim nograce&;
status = (clp,
clp-&cl_mvops-&nograce_recovery_ops);
if (status == -)
if (status & 0)
goto out_error;
if ((, &clp-&)) {
/* Did we race with an attempt to give us more work? */
if (clp-& == 0)
if ((, &clp-&) != 0)
} while ((&clp-&cl_count) & 1);
out_error:
section_sep = &: &;
(&NFS: state manager%s%s failed on NFSv4 server %s&
& with error %d\n&, section_sep, ,
clp-&cl_hostname, -status);
static int (void *)
* Local variables:
c-basic-offset: 8

我要回帖

更多关于 rotel rsp 1582 的文章

 

随机推荐