nfsd4: move client * to nfs4_stateid, add init_stid helper
[firefly-linux-kernel-4.4.55.git] / fs / nfsd / state.h
index 9745cc781e74436c9e287cb8520c7980ce7f25c4..70062b75e24ae981b0ad608dd34212eb43a7943e 100644 (file)
@@ -45,24 +45,20 @@ typedef struct {
 } clientid_t;
 
 typedef struct {
-       u32             so_boot;
-       u32             so_stateownerid;
-       u32             so_fileid;
+       clientid_t      so_clid;
+       u32             so_id;
 } stateid_opaque_t;
 
 typedef struct {
        u32                     si_generation;
        stateid_opaque_t        si_opaque;
 } stateid_t;
-#define si_boot           si_opaque.so_boot
-#define si_stateownerid   si_opaque.so_stateownerid
-#define si_fileid         si_opaque.so_fileid
 
 #define STATEID_FMT    "(%08x/%08x/%08x/%08x)"
 #define STATEID_VAL(s) \
-       (s)->si_boot, \
-       (s)->si_stateownerid, \
-       (s)->si_fileid, \
+       (s)->si_opaque.so_clid.cl_boot, \
+       (s)->si_opaque.so_clid.cl_id, \
+       (s)->si_opaque.so_id, \
        (s)->si_generation
 
 struct nfsd4_callback {
@@ -76,17 +72,28 @@ struct nfsd4_callback {
        bool cb_done;
 };
 
+struct nfs4_stid {
+#define NFS4_OPEN_STID 1
+#define NFS4_LOCK_STID 2
+#define NFS4_DELEG_STID 4
+/* For an open stateid kept around *only* to process close replays: */
+#define NFS4_CLOSED_STID 8
+       unsigned char sc_type;
+       struct list_head sc_hash;
+       stateid_t sc_stateid;
+       struct nfs4_client *sc_client;
+};
+
 struct nfs4_delegation {
        struct list_head        dl_perfile;
        struct list_head        dl_perclnt;
        struct list_head        dl_recall_lru;  /* delegation recalled */
        atomic_t                dl_count;       /* ref count */
-       struct nfs4_client      *dl_client;
        struct nfs4_file        *dl_file;
        u32                     dl_type;
        time_t                  dl_time;
 /* For recall: */
-       stateid_t               dl_stateid;
+       struct nfs4_stid        dl_stid;
        struct knfsd_fh         dl_fh;
        int                     dl_retries;
        struct nfsd4_callback   dl_recall;
@@ -104,6 +111,11 @@ struct nfs4_cb_conn {
        struct svc_xprt         *cb_xprt;       /* minorversion 1 only */
 };
 
+static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s)
+{
+       return container_of(s, struct nfs4_delegation, dl_stid);
+}
+
 /* Maximum number of slots per session. 160 is useful for long haul TCP */
 #define NFSD_MAX_SLOTS_PER_SESSION     160
 /* Maximum number of operations per session compound */
@@ -328,10 +340,10 @@ struct nfs4_replay {
 *         for lock_owner
 *    so_perclient: nfs4_client->cl_perclient entry - used when nfs4_client
 *         struct is reaped.
-*    so_perfilestate: heads the list of nfs4_stateid (either open or lock) 
-*         and is used to ensure no dangling nfs4_stateid references when we 
+*    so_perfilestate: heads the list of nfs4_ol_stateid (either open or lock) 
+*         and is used to ensure no dangling nfs4_ol_stateid references when we 
 *         release a stateowner.
-*    so_perlockowner: (open) nfs4_stateid->st_perlockowner entry - used when
+*    so_perlockowner: (open) nfs4_ol_stateid->st_perlockowner entry - used when
 *         close is called to reap associated byte-range locks
 *    so_close_lru: (open) stateowner is placed on this list instead of being
 *         reaped (when so_perfilestate is empty) to hold the last close replay.
@@ -339,11 +351,9 @@ struct nfs4_replay {
 */
 
 struct nfs4_stateowner {
-       struct list_head        so_idhash;   /* hash by so_id */
        struct list_head        so_strhash;   /* hash by op_name */
        struct list_head        so_stateids;
        int                     so_is_open_owner; /* 1=openowner,0=lockowner */
-       u32                     so_id;
        struct nfs4_client *    so_client;
        /* after increment in ENCODE_SEQID_OP_TAIL, represents the next
         * sequence id expected from the client: */
@@ -356,8 +366,11 @@ struct nfs4_openowner {
        struct nfs4_stateowner  oo_owner; /* must be first field */
        struct list_head        oo_perclient;
        struct list_head        oo_close_lru; /* tail queue */
+       struct nfs4_ol_stateid *oo_last_closed_stid;
        time_t                  oo_time; /* time of placement on so_close_lru */
-       int                     oo_confirmed; /* successful OPEN_CONFIRM? */
+#define NFS4_OO_CONFIRMED   1
+#define NFS4_OO_PURGE_CLOSE 2
+       unsigned char           oo_flags;
 };
 
 struct nfs4_lockowner {
@@ -398,8 +411,6 @@ struct nfs4_file {
        struct file_lock        *fi_lease;
        atomic_t                fi_delegees;
        struct inode            *fi_inode;
-       u32                     fi_id;      /* used with stateowner->so_id 
-                                            * for stateid_hashtbl hash */
        bool                    fi_had_conflict;
 };
 
@@ -430,9 +441,9 @@ static inline struct file *find_any_file(struct nfs4_file *f)
 }
 
 /*
-* nfs4_stateid can either be an open stateid or (eventually) a lock stateid
+* nfs4_ol_stateid can either be an open stateid or (eventually) a lock stateid
 *
-* (open)nfs4_stateid: one per (open)nfs4_stateowner, nfs4_file
+* (open)nfs4_ol_stateid: one per (open)nfs4_stateowner, nfs4_file
 *
 *      st_hash: stateid_hashtbl[] entry or lockstateid_hashtbl entry
 *      st_perfile: file_hashtbl[] entry.
@@ -446,25 +457,25 @@ static inline struct file *find_any_file(struct nfs4_file *f)
 * we should consider defining separate structs for the two cases.
 */
 
-struct nfs4_stateid {
-#define NFS4_OPEN_STID 1
-#define NFS4_LOCK_STID 2
-       char st_type;
-       struct list_head              st_hash; 
+/* "ol" stands for "Open or Lock".  Better suggestions welcome. */
+struct nfs4_ol_stateid {
+       struct nfs4_stid    st_stid;
        struct list_head              st_perfile;
        struct list_head              st_perstateowner;
        struct list_head              st_lockowners;
        struct nfs4_stateowner      * st_stateowner;
        struct nfs4_file            * st_file;
-       stateid_t                     st_stateid;
        unsigned long                 st_access_bmap;
        unsigned long                 st_deny_bmap;
-       struct nfs4_stateid         * st_openstp;
+       struct nfs4_ol_stateid         * st_openstp;
 };
 
+static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
+{
+       return container_of(s, struct nfs4_ol_stateid, st_stid);
+}
+
 /* flags for preprocess_seqid_op() */
-#define OPEN_STATE              0x00000004
-#define LOCK_STATE              0x00000008
 #define RD_STATE               0x00000010
 #define WR_STATE               0x00000020
 
@@ -499,5 +510,6 @@ 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 *);
 extern __be32 nfs4_validate_stateid(stateid_t *, bool);
+extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
 
 #endif   /* NFSD4_STATE_H */