]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/nfs/pnfs.h
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[net-next-2.6.git] / fs / nfs / pnfs.h
index 1c3eb02f494421160b2da9774489764a2f3246dc..e12367d504894ae15e9066d66446487fd69fa81e 100644 (file)
@@ -32,7 +32,7 @@
 
 struct pnfs_layout_segment {
        struct list_head fi_list;
-       u32 iomode;
+       struct pnfs_layout_range range;
        struct kref kref;
        struct pnfs_layout_hdr *layout;
 };
@@ -44,6 +44,7 @@ struct pnfs_layout_segment {
 enum {
        NFS_LAYOUT_RO_FAILED = 0,       /* get ro layout failed stop trying */
        NFS_LAYOUT_RW_FAILED,           /* get rw layout failed stop trying */
+       NFS_LAYOUT_STATEID_SET,         /* have a valid layout stateid */
 };
 
 /* Per-layout driver specific registration structure */
@@ -52,28 +53,98 @@ struct pnfs_layoutdriver_type {
        const u32 id;
        const char *name;
        struct module *owner;
-       int (*initialize_mountpoint) (struct nfs_server *);
-       int (*uninitialize_mountpoint) (struct nfs_server *);
+       int (*set_layoutdriver) (struct nfs_server *);
+       int (*clear_layoutdriver) (struct nfs_server *);
+       struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr);
+       void (*free_lseg) (struct pnfs_layout_segment *lseg);
 };
 
 struct pnfs_layout_hdr {
        unsigned long           refcount;
        struct list_head        layouts;   /* other client layouts */
        struct list_head        segs;      /* layout segments list */
+       seqlock_t               seqlock;   /* Protects the stateid */
+       nfs4_stateid            stateid;
        unsigned long           state;
        struct inode            *inode;
 };
 
+struct pnfs_device {
+       struct nfs4_deviceid dev_id;
+       unsigned int  layout_type;
+       unsigned int  mincount;
+       struct page **pages;
+       void          *area;
+       unsigned int  pgbase;
+       unsigned int  pglen;
+};
+
+/*
+ * Device ID RCU cache. A device ID is unique per client ID and layout type.
+ */
+#define NFS4_DEVICE_ID_HASH_BITS       5
+#define NFS4_DEVICE_ID_HASH_SIZE       (1 << NFS4_DEVICE_ID_HASH_BITS)
+#define NFS4_DEVICE_ID_HASH_MASK       (NFS4_DEVICE_ID_HASH_SIZE - 1)
+
+static inline u32
+nfs4_deviceid_hash(struct nfs4_deviceid *id)
+{
+       unsigned char *cptr = (unsigned char *)id->data;
+       unsigned int nbytes = NFS4_DEVICEID4_SIZE;
+       u32 x = 0;
+
+       while (nbytes--) {
+               x *= 37;
+               x += *cptr++;
+       }
+       return x & NFS4_DEVICE_ID_HASH_MASK;
+}
+
+struct pnfs_deviceid_node {
+       struct hlist_node       de_node;
+       struct nfs4_deviceid    de_id;
+       atomic_t                de_ref;
+};
+
+struct pnfs_deviceid_cache {
+       spinlock_t              dc_lock;
+       atomic_t                dc_ref;
+       void                    (*dc_free_callback)(struct pnfs_deviceid_node *);
+       struct hlist_head       dc_deviceids[NFS4_DEVICE_ID_HASH_SIZE];
+};
+
+extern int pnfs_alloc_init_deviceid_cache(struct nfs_client *,
+                       void (*free_callback)(struct pnfs_deviceid_node *));
+extern void pnfs_put_deviceid_cache(struct nfs_client *);
+extern struct pnfs_deviceid_node *pnfs_find_get_deviceid(
+                               struct pnfs_deviceid_cache *,
+                               struct nfs4_deviceid *);
+extern struct pnfs_deviceid_node *pnfs_add_deviceid(
+                               struct pnfs_deviceid_cache *,
+                               struct pnfs_deviceid_node *);
+extern void pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
+                             struct pnfs_deviceid_node *devid);
+
 extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
 extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
 
+/* nfs4proc.c */
+extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
+                                  struct pnfs_device *dev);
+extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp);
+
+/* pnfs.c */
 struct pnfs_layout_segment *
 pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
                   enum pnfs_iomode access_type);
 void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
 void unset_pnfs_layoutdriver(struct nfs_server *);
+int pnfs_layout_process(struct nfs4_layoutget *lgp);
 void pnfs_destroy_layout(struct nfs_inode *);
 void pnfs_destroy_all_layouts(struct nfs_client *);
+void put_layout_hdr(struct inode *inode);
+void pnfs_get_layout_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
+                            struct nfs4_state *open_state);
 
 
 static inline int lo_fail_bit(u32 iomode)