]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/nfs/blocklayout/blocklayout.h
pnfs/blocklayout: in-kernel GETDEVICEINFO XDR parsing
[karo-tx-linux.git] / fs / nfs / blocklayout / blocklayout.h
index 9838fb020473c935817b34da4a1127b4c75af3fe..92dca9e90d8dab527d3b5d3b6891981aeb77de11 100644 (file)
 #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT)
 #define SECTOR_SIZE (1 << SECTOR_SHIFT)
 
-struct block_mount_id {
-       spinlock_t                      bm_lock;    /* protects list */
-       struct list_head                bm_devlist; /* holds pnfs_block_dev */
-};
+struct pnfs_block_dev;
 
-struct pnfs_block_dev {
-       struct list_head                bm_node;
-       struct nfs4_deviceid            bm_mdevid;    /* associated devid */
-       struct block_device             *bm_mdev;     /* meta device itself */
-       struct net                      *net;
+enum pnfs_block_volume_type {
+       PNFS_BLOCK_VOLUME_SIMPLE        = 0,
+       PNFS_BLOCK_VOLUME_SLICE         = 1,
+       PNFS_BLOCK_VOLUME_CONCAT        = 2,
+       PNFS_BLOCK_VOLUME_STRIPE        = 3,
 };
 
-enum exstate4 {
-       PNFS_BLOCK_READWRITE_DATA       = 0,
-       PNFS_BLOCK_READ_DATA            = 1,
-       PNFS_BLOCK_INVALID_DATA         = 2, /* mapped, but data is invalid */
-       PNFS_BLOCK_NONE_DATA            = 3  /* unmapped, it's a hole */
+#define PNFS_BLOCK_MAX_UUIDS   4
+#define PNFS_BLOCK_MAX_DEVICES 64
+
+/*
+ * Random upper cap for the uuid length to avoid unbounded allocation.
+ * Not actually limited by the protocol.
+ */
+#define PNFS_BLOCK_UUID_LEN    128
+
+
+struct pnfs_block_volume {
+       enum pnfs_block_volume_type     type;
+       union {
+               struct {
+                       int             len;
+                       int             nr_sigs;
+                       struct {
+                               u64             offset;
+                               u32             sig_len;
+                               u8              sig[PNFS_BLOCK_UUID_LEN];
+                       } sigs[PNFS_BLOCK_MAX_UUIDS];
+               } simple;
+               struct {
+                       u64             start;
+                       u64             len;
+                       u32             volume;
+               } slice;
+               struct {
+                       u32             volumes_count;
+                       u32             volumes[PNFS_BLOCK_MAX_DEVICES];
+               } concat;
+               struct {
+                       u64             chunk_size;
+                       u32             volumes_count;
+                       u32             volumes[PNFS_BLOCK_MAX_DEVICES];
+               } stripe;
+       };
 };
 
-#define MY_MAX_TAGS (15) /* tag bitnums used must be less than this */
+struct pnfs_block_dev_map {
+       sector_t                        start;
+       sector_t                        len;
 
-struct my_tree {
-       sector_t                mtt_step_size;  /* Internal sector alignment */
-       struct list_head        mtt_stub; /* Should be a radix tree */
+       sector_t                        disk_offset;
+       struct block_device             *bdev;
 };
 
-struct pnfs_inval_markings {
-       spinlock_t      im_lock;
-       struct my_tree  im_tree;        /* Sectors that need LAYOUTCOMMIT */
-       sector_t        im_block_size;  /* Server blocksize in sectors */
-       struct list_head im_extents;    /* Short extents for INVAL->RW conversion */
+struct pnfs_block_dev {
+       struct nfs4_deviceid_node       node;
+
+       u64                             start;
+       u64                             len;
+
+       u32                             nr_children;
+       struct pnfs_block_dev           *children;
+       u64                             chunk_size;
+
+       struct block_device             *bdev;
+       u64                             disk_offset;
+
+       bool (*map)(struct pnfs_block_dev *dev, u64 offset,
+                       struct pnfs_block_dev_map *map);
 };
 
-struct pnfs_inval_tracking {
-       struct list_head it_link;
-       int              it_sector;
-       int              it_tags;
+enum exstate4 {
+       PNFS_BLOCK_READWRITE_DATA       = 0,
+       PNFS_BLOCK_READ_DATA            = 1,
+       PNFS_BLOCK_INVALID_DATA         = 2, /* mapped, but data is invalid */
+       PNFS_BLOCK_NONE_DATA            = 3  /* unmapped, it's a hole */
 };
 
 /* sector_t fields are all in 512-byte sectors */
 struct pnfs_block_extent {
-       struct kref     be_refcnt;
-       struct list_head be_node;       /* link into lseg list */
-       struct nfs4_deviceid be_devid;  /* FIXME: could use device cache instead */
-       struct block_device *be_mdev;
+       union {
+               struct rb_node  be_node;
+               struct list_head be_list;
+       };
+       struct nfs4_deviceid_node *be_device;
        sector_t        be_f_offset;    /* the starting offset in the file */
        sector_t        be_length;      /* the size of the extent */
        sector_t        be_v_offset;    /* the starting offset in the volume */
        enum exstate4   be_state;       /* the state of this extent */
-       struct pnfs_inval_markings *be_inval; /* tracks INVAL->RW transition */
+#define EXTENT_WRITTEN         1
+#define EXTENT_COMMITTING      2
+       unsigned int    be_tag;
 };
 
-/* Shortened extent used by LAYOUTCOMMIT */
-struct pnfs_block_short_extent {
-       struct list_head bse_node;
-       struct nfs4_deviceid bse_devid;
-       struct block_device *bse_mdev;
-       sector_t        bse_f_offset;   /* the starting offset in the file */
-       sector_t        bse_length;     /* the size of the extent */
-};
-
-static inline void
-BL_INIT_INVAL_MARKS(struct pnfs_inval_markings *marks, sector_t blocksize)
-{
-       spin_lock_init(&marks->im_lock);
-       INIT_LIST_HEAD(&marks->im_tree.mtt_stub);
-       INIT_LIST_HEAD(&marks->im_extents);
-       marks->im_block_size = blocksize;
-       marks->im_tree.mtt_step_size = min((sector_t)PAGE_CACHE_SECTORS,
-                                          blocksize);
-}
-
-enum extentclass4 {
-       RW_EXTENT       = 0, /* READWRTE and INVAL */
-       RO_EXTENT       = 1, /* READ and NONE */
-       EXTENT_LISTS    = 2,
-};
-
-static inline int bl_choose_list(enum exstate4 state)
-{
-       if (state == PNFS_BLOCK_READ_DATA || state == PNFS_BLOCK_NONE_DATA)
-               return RO_EXTENT;
-       else
-               return RW_EXTENT;
-}
+/* on the wire size of the extent */
+#define BL_EXTENT_SIZE (7 * sizeof(__be32) + NFS4_DEVICEID4_SIZE)
 
 struct pnfs_block_layout {
-       struct pnfs_layout_hdr bl_layout;
-       struct pnfs_inval_markings bl_inval; /* tracks INVAL->RW transition */
+       struct pnfs_layout_hdr  bl_layout;
+       struct rb_root          bl_ext_rw;
+       struct rb_root          bl_ext_ro;
        spinlock_t              bl_ext_lock;   /* Protects list manipulation */
-       struct list_head        bl_extents[EXTENT_LISTS]; /* R and RW extents */
-       struct list_head        bl_commit;      /* Needs layout commit */
-       struct list_head        bl_committing;  /* Layout committing */
-       unsigned int            bl_count;       /* entries in bl_commit */
-       sector_t                bl_blocksize;  /* Server blocksize in sectors */
 };
 
-#define BLK_ID(lo) ((struct block_mount_id *)(NFS_SERVER(lo->plh_inode)->pnfs_ld_data))
-
 static inline struct pnfs_block_layout *
 BLK_LO2EXT(struct pnfs_layout_hdr *lo)
 {
@@ -171,41 +178,27 @@ struct bl_msg_hdr {
 #define BL_DEVICE_REQUEST_PROC         0x1 /* User level process succeeds */
 #define BL_DEVICE_REQUEST_ERR          0x2 /* User level process fails */
 
-/* blocklayoutdev.c */
-ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t);
-void bl_pipe_destroy_msg(struct rpc_pipe_msg *);
-void nfs4_blkdev_put(struct block_device *bdev);
-struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server,
-                                               struct pnfs_device *dev);
-int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo,
-                               struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
-
-/* blocklayoutdm.c */
-void bl_free_block_dev(struct pnfs_block_dev *bdev);
-
-/* extents.c */
-struct pnfs_block_extent *
-bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect,
-               struct pnfs_block_extent **cow_read);
-int bl_mark_sectors_init(struct pnfs_inval_markings *marks,
-                            sector_t offset, sector_t length);
-void bl_put_extent(struct pnfs_block_extent *be);
-struct pnfs_block_extent *bl_alloc_extent(void);
-int bl_is_sector_init(struct pnfs_inval_markings *marks, sector_t isect);
-int encode_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
-                                  struct xdr_stream *xdr,
-                                  const struct nfs4_layoutcommit_args *arg);
-void clean_pnfs_block_layoutupdate(struct pnfs_block_layout *bl,
-                                  const struct nfs4_layoutcommit_args *arg,
-                                  int status);
-int bl_add_merge_extent(struct pnfs_block_layout *bl,
-                        struct pnfs_block_extent *new);
-int bl_mark_for_commit(struct pnfs_block_extent *be,
-                       sector_t offset, sector_t length,
-                       struct pnfs_block_short_extent *new);
-int bl_push_one_short_extent(struct pnfs_inval_markings *marks);
-struct pnfs_block_short_extent *
-bl_pop_one_short_extent(struct pnfs_inval_markings *marks);
-void bl_free_short_extents(struct pnfs_inval_markings *marks, int num_to_free);
+/* dev.c */
+struct nfs4_deviceid_node *bl_alloc_deviceid_node(struct nfs_server *server,
+               struct pnfs_device *pdev, gfp_t gfp_mask);
+void bl_free_deviceid_node(struct nfs4_deviceid_node *d);
+
+/* extent_tree.c */
+int ext_tree_insert(struct pnfs_block_layout *bl,
+               struct pnfs_block_extent *new);
+int ext_tree_remove(struct pnfs_block_layout *bl, bool rw, sector_t start,
+               sector_t end);
+int ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
+               sector_t len);
+bool ext_tree_lookup(struct pnfs_block_layout *bl, sector_t isect,
+               struct pnfs_block_extent *ret, bool rw);
+int ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg);
+void ext_tree_mark_committed(struct nfs4_layoutcommit_args *arg, int status);
+
+/* rpc_pipefs.c */
+dev_t bl_resolve_deviceid(struct nfs_server *server,
+               struct pnfs_block_volume *b, gfp_t gfp_mask);
+int __init bl_init_pipefs(void);
+void __exit bl_cleanup_pipefs(void);
 
 #endif /* FS_NFS_NFS4BLOCKLAYOUT_H */