nfsd: Add reference counting to the lock and open stateids
[cascardo/linux.git] / fs / nfsd / state.h
index 374c662..32c4662 100644 (file)
@@ -73,6 +73,7 @@ struct nfsd4_callback {
 };
 
 struct nfs4_stid {
+       atomic_t sc_count;
 #define NFS4_OPEN_STID 1
 #define NFS4_LOCK_STID 2
 #define NFS4_DELEG_STID 4
@@ -80,9 +81,11 @@ struct nfs4_stid {
 #define NFS4_CLOSED_STID 8
 /* For a deleg stateid kept around only to process free_stateid's: */
 #define NFS4_REVOKED_DELEG_STID 16
+#define NFS4_CLOSED_DELEG_STID 32
        unsigned char sc_type;
        stateid_t sc_stateid;
        struct nfs4_client *sc_client;
+       void (*sc_free)(struct nfs4_stid *);
 };
 
 struct nfs4_delegation {
@@ -90,12 +93,10 @@ 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_file        *dl_file;
        u32                     dl_type;
        time_t                  dl_time;
 /* For recall: */
-       struct knfsd_fh         dl_fh;
        int                     dl_retries;
        struct nfsd4_callback   dl_recall;
 };
@@ -212,8 +213,6 @@ struct nfsd4_session {
        struct nfsd4_slot       *se_slots[];    /* forward channel slots */
 };
 
-extern void nfsd4_put_session(struct nfsd4_session *ses);
-
 /* formatted contents of nfs4_sessionid */
 struct nfsd4_sessionid {
        clientid_t      clientid;
@@ -364,9 +363,6 @@ struct nfs4_openowner {
 
 struct nfs4_lockowner {
        struct nfs4_stateowner  lo_owner; /* must be first element */
-       struct list_head        lo_owner_ino_hash; /* hash by owner,file */
-       struct list_head        lo_perstateid;
-       struct list_head        lo_list; /* for temporary uses */
 };
 
 static inline struct nfs4_openowner * openowner(struct nfs4_stateowner *so)
@@ -382,6 +378,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so)
 /* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */
 struct nfs4_file {
        atomic_t                fi_ref;
+       spinlock_t              fi_lock;
        struct hlist_node       fi_hash;    /* hash by "struct inode *" */
        struct list_head        fi_stateids;
        struct list_head        fi_delegations;
@@ -395,49 +392,24 @@ struct nfs4_file {
         *   + 1 to both of the above if NFS4_SHARE_ACCESS_BOTH is set.
         */
        atomic_t                fi_access[2];
+       u32                     fi_share_deny;
        struct file             *fi_deleg_file;
        struct file_lock        *fi_lease;
        atomic_t                fi_delegees;
-       struct inode            *fi_inode;
+       struct knfsd_fh         fi_fhandle;
        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];
-}
-
 /* "ol" stands for "Open or Lock".  Better suggestions welcome. */
 struct nfs4_ol_stateid {
        struct nfs4_stid    st_stid; /* must be first field */
        struct list_head              st_perfile;
        struct list_head              st_perstateowner;
-       struct list_head              st_lockowners;
+       struct list_head              st_locks;
        struct nfs4_stateowner      * st_stateowner;
        struct nfs4_file            * st_file;
-       unsigned long                 st_access_bmap;
-       unsigned long                 st_deny_bmap;
+       unsigned char                 st_access_bmap;
+       unsigned char                 st_deny_bmap;
        struct nfs4_ol_stateid         * st_openstp;
 };
 
@@ -458,13 +430,16 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net,
                stateid_t *stateid, int flags, struct file **filp);
 extern void nfs4_lock_state(void);
 extern void nfs4_unlock_state(void);
+void nfs4_put_stid(struct nfs4_stid *s);
 void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *);
 extern void nfs4_release_reclaim(struct nfsd_net *);
 extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
                                                        struct nfsd_net *nn);
-extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn);
+extern __be32 nfs4_check_open_reclaim(clientid_t *clid,
+               struct nfsd4_compound_state *cstate, struct nfsd_net *nn);
 extern int set_callback_cred(void);
-extern void nfsd4_init_callback(struct nfsd4_callback *);
+void nfsd4_run_cb_null(struct work_struct *w);
+void nfsd4_run_cb_recall(struct work_struct *w);
 extern void nfsd4_probe_callback(struct nfs4_client *clp);
 extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
 extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
@@ -472,11 +447,10 @@ extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
 extern int nfsd4_create_callback_queue(void);
 extern void nfsd4_destroy_callback_queue(void);
 extern void nfsd4_shutdown_callback(struct nfs4_client *);
-extern void nfs4_put_delegation(struct nfs4_delegation *dp);
+extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp);
 extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
                                                        struct nfsd_net *nn);
 extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
-extern void put_client_renew(struct nfs4_client *clp);
 
 /* nfs4recover operations */
 extern int nfsd4_client_tracking_init(struct net *net);