linux/fs/nfs/pnfs.h
<<
>>
Prefs
   1/*
   2 *  pNFS client data structures.
   3 *
   4 *  Copyright (c) 2002
   5 *  The Regents of the University of Michigan
   6 *  All Rights Reserved
   7 *
   8 *  Dean Hildebrand <dhildebz@umich.edu>
   9 *
  10 *  Permission is granted to use, copy, create derivative works, and
  11 *  redistribute this software and such derivative works for any purpose,
  12 *  so long as the name of the University of Michigan is not used in
  13 *  any advertising or publicity pertaining to the use or distribution
  14 *  of this software without specific, written prior authorization. If
  15 *  the above copyright notice or any other identification of the
  16 *  University of Michigan is included in any copy of any portion of
  17 *  this software, then the disclaimer below must also be included.
  18 *
  19 *  This software is provided as is, without representation or warranty
  20 *  of any kind either express or implied, including without limitation
  21 *  the implied warranties of merchantability, fitness for a particular
  22 *  purpose, or noninfringement.  The Regents of the University of
  23 *  Michigan shall not be liable for any damages, including special,
  24 *  indirect, incidental, or consequential damages, with respect to any
  25 *  claim arising out of or in connection with the use of the software,
  26 *  even if it has been or is hereafter advised of the possibility of
  27 *  such damages.
  28 */
  29
  30#ifndef FS_NFS_PNFS_H
  31#define FS_NFS_PNFS_H
  32
  33#include <linux/nfs_page.h>
  34
  35enum {
  36        NFS_LSEG_VALID = 0,     /* cleared when lseg is recalled/returned */
  37        NFS_LSEG_ROC,           /* roc bit received from server */
  38};
  39
  40struct pnfs_layout_segment {
  41        struct list_head pls_list;
  42        struct pnfs_layout_range pls_range;
  43        atomic_t pls_refcount;
  44        unsigned long pls_flags;
  45        struct pnfs_layout_hdr *pls_layout;
  46        struct rpc_cred *pls_lc_cred; /* LAYOUTCOMMIT credential */
  47        loff_t pls_end_pos; /* LAYOUTCOMMIT write end */
  48};
  49
  50enum pnfs_try_status {
  51        PNFS_ATTEMPTED     = 0,
  52        PNFS_NOT_ATTEMPTED = 1,
  53};
  54
  55#ifdef CONFIG_NFS_V4_1
  56
  57#define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4"
  58
  59enum {
  60        NFS_LAYOUT_RO_FAILED = 0,       /* get ro layout failed stop trying */
  61        NFS_LAYOUT_RW_FAILED,           /* get rw layout failed stop trying */
  62        NFS_LAYOUT_BULK_RECALL,         /* bulk recall affecting layout */
  63        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
  64        NFS_LAYOUT_DESTROYED,           /* no new use of layout allowed */
  65};
  66
  67/* Per-layout driver specific registration structure */
  68struct pnfs_layoutdriver_type {
  69        struct list_head pnfs_tblid;
  70        const u32 id;
  71        const char *name;
  72        struct module *owner;
  73        struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr, gfp_t gfp_flags);
  74        void (*free_lseg) (struct pnfs_layout_segment *lseg);
  75
  76        /* test for nfs page cache coalescing */
  77        int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
  78
  79        /* Returns true if layoutdriver wants to divert this request to
  80         * driver's commit routine.
  81         */
  82        bool (*mark_pnfs_commit)(struct pnfs_layout_segment *lseg);
  83        struct list_head * (*choose_commit_list) (struct nfs_page *req);
  84        int (*commit_pagelist)(struct inode *inode, struct list_head *mds_pages, int how);
  85
  86        /*
  87         * Return PNFS_ATTEMPTED to indicate the layout code has attempted
  88         * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS
  89         */
  90        enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data);
  91        enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data, int how);
  92};
  93
  94struct pnfs_layout_hdr {
  95        atomic_t                plh_refcount;
  96        struct list_head        plh_layouts;   /* other client layouts */
  97        struct list_head        plh_bulk_recall; /* clnt list of bulk recalls */
  98        struct list_head        plh_segs;      /* layout segments list */
  99        nfs4_stateid            plh_stateid;
 100        atomic_t                plh_outstanding; /* number of RPCs out */
 101        unsigned long           plh_block_lgets; /* block LAYOUTGET if >0 */
 102        u32                     plh_barrier; /* ignore lower seqids */
 103        unsigned long           plh_flags;
 104        struct inode            *plh_inode;
 105};
 106
 107struct pnfs_device {
 108        struct nfs4_deviceid dev_id;
 109        unsigned int  layout_type;
 110        unsigned int  mincount;
 111        struct page **pages;
 112        unsigned int  pgbase;
 113        unsigned int  pglen;
 114};
 115
 116extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
 117extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
 118
 119/* nfs4proc.c */
 120extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
 121                                   struct pnfs_device *dev);
 122extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp);
 123
 124/* pnfs.c */
 125void get_layout_hdr(struct pnfs_layout_hdr *lo);
 126void put_lseg(struct pnfs_layout_segment *lseg);
 127struct pnfs_layout_segment *
 128pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
 129                   enum pnfs_iomode access_type, gfp_t gfp_flags);
 130void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
 131void unset_pnfs_layoutdriver(struct nfs_server *);
 132enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
 133                                             const struct rpc_call_ops *, int);
 134enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *,
 135                                            const struct rpc_call_ops *);
 136void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
 137void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *);
 138int pnfs_layout_process(struct nfs4_layoutget *lgp);
 139void pnfs_free_lseg_list(struct list_head *tmp_list);
 140void pnfs_destroy_layout(struct nfs_inode *);
 141void pnfs_destroy_all_layouts(struct nfs_client *);
 142void put_layout_hdr(struct pnfs_layout_hdr *lo);
 143void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
 144                             const nfs4_stateid *new,
 145                             bool update_barrier);
 146int pnfs_choose_layoutget_stateid(nfs4_stateid *dst,
 147                                  struct pnfs_layout_hdr *lo,
 148                                  struct nfs4_state *open_state);
 149int mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
 150                                struct list_head *tmp_list,
 151                                u32 iomode);
 152bool pnfs_roc(struct inode *ino);
 153void pnfs_roc_release(struct inode *ino);
 154void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);
 155bool pnfs_roc_drain(struct inode *ino, u32 *barrier);
 156void pnfs_set_layoutcommit(struct nfs_write_data *wdata);
 157int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
 158
 159static inline int lo_fail_bit(u32 iomode)
 160{
 161        return iomode == IOMODE_RW ?
 162                         NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED;
 163}
 164
 165static inline struct pnfs_layout_segment *
 166get_lseg(struct pnfs_layout_segment *lseg)
 167{
 168        if (lseg) {
 169                atomic_inc(&lseg->pls_refcount);
 170                smp_mb__after_atomic_inc();
 171        }
 172        return lseg;
 173}
 174
 175/* Return true if a layout driver is being used for this mountpoint */
 176static inline int pnfs_enabled_sb(struct nfs_server *nfss)
 177{
 178        return nfss->pnfs_curr_ld != NULL;
 179}
 180
 181static inline void
 182pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg)
 183{
 184        if (lseg) {
 185                struct pnfs_layoutdriver_type *ld;
 186
 187                ld = NFS_SERVER(req->wb_page->mapping->host)->pnfs_curr_ld;
 188                if (ld->mark_pnfs_commit && ld->mark_pnfs_commit(lseg)) {
 189                        set_bit(PG_PNFS_COMMIT, &req->wb_flags);
 190                        req->wb_commit_lseg = get_lseg(lseg);
 191                }
 192        }
 193}
 194
 195static inline int
 196pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how)
 197{
 198        if (!test_and_clear_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags))
 199                return PNFS_NOT_ATTEMPTED;
 200        return NFS_SERVER(inode)->pnfs_curr_ld->commit_pagelist(inode, mds_pages, how);
 201}
 202
 203static inline struct list_head *
 204pnfs_choose_commit_list(struct nfs_page *req, struct list_head *mds)
 205{
 206        struct list_head *rv;
 207
 208        if (test_and_clear_bit(PG_PNFS_COMMIT, &req->wb_flags)) {
 209                struct inode *inode = req->wb_commit_lseg->pls_layout->plh_inode;
 210
 211                set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags);
 212                rv = NFS_SERVER(inode)->pnfs_curr_ld->choose_commit_list(req);
 213                /* matched by ref taken when PG_PNFS_COMMIT is set */
 214                put_lseg(req->wb_commit_lseg);
 215        } else
 216                rv = mds;
 217        return rv;
 218}
 219
 220static inline void pnfs_clear_request_commit(struct nfs_page *req)
 221{
 222        if (test_and_clear_bit(PG_PNFS_COMMIT, &req->wb_flags))
 223                put_lseg(req->wb_commit_lseg);
 224}
 225
 226#else  /* CONFIG_NFS_V4_1 */
 227
 228static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
 229{
 230}
 231
 232static inline void pnfs_destroy_layout(struct nfs_inode *nfsi)
 233{
 234}
 235
 236static inline struct pnfs_layout_segment *
 237get_lseg(struct pnfs_layout_segment *lseg)
 238{
 239        return NULL;
 240}
 241
 242static inline void put_lseg(struct pnfs_layout_segment *lseg)
 243{
 244}
 245
 246static inline struct pnfs_layout_segment *
 247pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
 248                   enum pnfs_iomode access_type, gfp_t gfp_flags)
 249{
 250        return NULL;
 251}
 252
 253static inline enum pnfs_try_status
 254pnfs_try_to_read_data(struct nfs_read_data *data,
 255                      const struct rpc_call_ops *call_ops)
 256{
 257        return PNFS_NOT_ATTEMPTED;
 258}
 259
 260static inline enum pnfs_try_status
 261pnfs_try_to_write_data(struct nfs_write_data *data,
 262                       const struct rpc_call_ops *call_ops, int how)
 263{
 264        return PNFS_NOT_ATTEMPTED;
 265}
 266
 267static inline bool
 268pnfs_roc(struct inode *ino)
 269{
 270        return false;
 271}
 272
 273static inline void
 274pnfs_roc_release(struct inode *ino)
 275{
 276}
 277
 278static inline void
 279pnfs_roc_set_barrier(struct inode *ino, u32 barrier)
 280{
 281}
 282
 283static inline bool
 284pnfs_roc_drain(struct inode *ino, u32 *barrier)
 285{
 286        return false;
 287}
 288
 289static inline void set_pnfs_layoutdriver(struct nfs_server *s, u32 id)
 290{
 291}
 292
 293static inline void unset_pnfs_layoutdriver(struct nfs_server *s)
 294{
 295}
 296
 297static inline void
 298pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *ino)
 299{
 300        pgio->pg_test = NULL;
 301}
 302
 303static inline void
 304pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *ino)
 305{
 306        pgio->pg_test = NULL;
 307}
 308
 309static inline void
 310pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg)
 311{
 312}
 313
 314static inline int
 315pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how)
 316{
 317        return PNFS_NOT_ATTEMPTED;
 318}
 319
 320static inline struct list_head *
 321pnfs_choose_commit_list(struct nfs_page *req, struct list_head *mds)
 322{
 323        return mds;
 324}
 325
 326static inline void pnfs_clear_request_commit(struct nfs_page *req)
 327{
 328}
 329
 330static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync)
 331{
 332        return 0;
 333}
 334#endif /* CONFIG_NFS_V4_1 */
 335
 336#endif /* FS_NFS_PNFS_H */
 337