]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/nfsd/state.h
nfsd4: fix downgrade/lock logic
[net-next-2.6.git] / fs / nfsd / state.h
index cef20abf330c6bd6e5cfed9a94305cd0e24cbd4b..322518c88e4b09eee40473ed8efaece99e02410b 100644 (file)
@@ -88,7 +88,6 @@ struct nfs4_delegation {
        struct nfs4_client      *dl_client;
        struct nfs4_file        *dl_file;
        struct file_lock        *dl_flock;
-       struct file             *dl_vfs_file;
        u32                     dl_type;
        time_t                  dl_time;
 /* For recall: */
@@ -107,9 +106,7 @@ struct nfs4_cb_conn {
        u32                     cb_prog;
        u32                     cb_minorversion;
        u32                     cb_ident;       /* minorversion 0 only */
-       /* RPC client info */
-       atomic_t                cb_set;     /* successful CB_NULL call */
-       struct rpc_clnt *       cb_client;
+       struct svc_xprt         *cb_xprt;       /* minorversion 1 only */
 };
 
 /* Maximum number of slots per session. 160 is useful for long haul TCP */
@@ -168,7 +165,7 @@ struct nfsd4_session {
        struct list_head        se_hash;        /* hash by sessionid */
        struct list_head        se_perclnt;
        u32                     se_flags;
-       struct nfs4_client      *se_client;     /* for expire_client */
+       struct nfs4_client      *se_client;
        struct nfs4_sessionid   se_sessionid;
        struct nfsd4_channel_attrs se_fchannel;
        struct nfsd4_channel_attrs se_bchannel;
@@ -223,24 +220,41 @@ struct nfs4_client {
        struct svc_cred         cl_cred;        /* setclientid principal */
        clientid_t              cl_clientid;    /* generated by server */
        nfs4_verifier           cl_confirm;     /* generated by server */
-       struct nfs4_cb_conn     cl_cb_conn;     /* callback info */
        u32                     cl_firststate;  /* recovery dir creation */
 
+       /* for v4.0 and v4.1 callbacks: */
+       struct nfs4_cb_conn     cl_cb_conn;
+       struct rpc_clnt         *cl_cb_client;
+       atomic_t                cl_cb_set;
+
        /* for nfs41 */
        struct list_head        cl_sessions;
        struct nfsd4_clid_slot  cl_cs_slot;     /* create_session slot */
        u32                     cl_exchange_flags;
        struct nfs4_sessionid   cl_sessionid;
+       /* number of rpc's in progress over an associated session: */
+       atomic_t                cl_refcount;
 
        /* for nfs41 callbacks */
        /* We currently support a single back channel with a single slot */
        unsigned long           cl_cb_slot_busy;
        u32                     cl_cb_seq_nr;
-       struct svc_xprt         *cl_cb_xprt;    /* 4.1 callback transport */
        struct rpc_wait_queue   cl_cb_waitq;    /* backchannel callers may */
                                                /* wait here for slots */
 };
 
+static inline void
+mark_client_expired(struct nfs4_client *clp)
+{
+       clp->cl_time = 0;
+}
+
+static inline bool
+is_client_expired(struct nfs4_client *clp)
+{
+       return clp->cl_time == 0;
+}
+
 /* struct nfs4_client_reset
  * one per old client. Populates reset_str_hashtbl. Filled from conf_id_hashtbl
  * upon lease reset, or from upcall to state_daemon (to read in state
@@ -327,12 +341,50 @@ struct nfs4_file {
        struct list_head        fi_hash;    /* hash by "struct inode *" */
        struct list_head        fi_stateids;
        struct list_head        fi_delegations;
+       /* One each for O_RDONLY, O_WRONLY, O_RDWR: */
+       struct file *           fi_fds[3];
+       /* One each for O_RDONLY, O_WRONLY: */
+       atomic_t                fi_access[2];
+       /*
+        * Each open stateid contributes 1 to either fi_readers or
+        * fi_writers, or both, depending on the open mode.  A
+        * delegation also takes an fi_readers reference.  Lock
+        * stateid's take none.
+        */
+       atomic_t                fi_readers;
+       atomic_t                fi_writers;
        struct inode            *fi_inode;
        u32                     fi_id;      /* used with stateowner->so_id 
                                             * for stateid_hashtbl hash */
        bool                    fi_had_conflict;
 };
 
+/* XXX: for first cut may fall back on returning file that doesn't work
+ * at all? */
+static inline struct file *find_writeable_file(struct nfs4_file *f)
+{
+       if (f->fi_fds[O_WRONLY])
+               return f->fi_fds[O_WRONLY];
+       return f->fi_fds[O_RDWR];
+}
+
+static inline struct file *find_readable_file(struct nfs4_file *f)
+{
+       if (f->fi_fds[O_RDONLY])
+               return f->fi_fds[O_RDONLY];
+       return f->fi_fds[O_RDWR];
+}
+
+static inline struct file *find_any_file(struct nfs4_file *f)
+{
+       if (f->fi_fds[O_RDWR])
+               return f->fi_fds[O_RDWR];
+       else if (f->fi_fds[O_WRONLY])
+               return f->fi_fds[O_WRONLY];
+       else
+               return f->fi_fds[O_RDONLY];
+}
+
 /*
 * nfs4_stateid can either be an open stateid or (eventually) a lock stateid
 *
@@ -358,7 +410,6 @@ struct nfs4_stateid {
        struct nfs4_stateowner      * st_stateowner;
        struct nfs4_file            * st_file;
        stateid_t                     st_stateid;
-       struct file                 * st_vfs_file;
        unsigned long                 st_access_bmap;
        unsigned long                 st_deny_bmap;
        struct nfs4_stateid         * st_openstp;
@@ -389,7 +440,7 @@ extern int nfs4_in_grace(void);
 extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
 extern void nfs4_free_stateowner(struct kref *kref);
 extern int set_callback_cred(void);
-extern void nfsd4_probe_callback(struct nfs4_client *clp);
+extern void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
 extern void nfsd4_do_callback_rpc(struct work_struct *);
 extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
 extern int nfsd4_create_callback_queue(void);
@@ -405,6 +456,7 @@ extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
 extern void nfsd4_recdir_purge_old(void);
 extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
 extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
+extern void release_session_client(struct nfsd4_session *);
 
 static inline void
 nfs4_put_stateowner(struct nfs4_stateowner *so)