flexfilelayout.h 6.4 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2 3 4 5 6 7 8 9 10 11 12
/*
 * NFSv4 flexfile layout driver data structures.
 *
 * Copyright (c) 2014, Primary Data, Inc. All rights reserved.
 *
 * Tao Peng <bergwolf@primarydata.com>
 */

#ifndef FS_NFS_NFS4FLEXFILELAYOUT_H
#define FS_NFS_NFS4FLEXFILELAYOUT_H

13
#define FF_FLAGS_NO_LAYOUTCOMMIT 1
14 15
#define FF_FLAGS_NO_IO_THRU_MDS  2
#define FF_FLAGS_NO_READ_IO      4
16

17
#include <linux/refcount.h>
18 19 20 21 22 23
#include "../pnfs.h"

/* XXX: Let's filter out insanely large mirror count for now to avoid oom
 * due to network error etc. */
#define NFS4_FLEXFILE_LAYOUT_MAX_MIRROR_CNT 4096

24 25
/* LAYOUTSTATS report interval in ms */
#define FF_LAYOUTSTATS_REPORT_INTERVAL (60000L)
26
#define FF_LAYOUTSTATS_MAXDEV 4
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
struct nfs4_ff_ds_version {
	u32				version;
	u32				minor_version;
	u32				rsize;
	u32				wsize;
	bool				tightly_coupled;
};

/* chained in global deviceid hlist */
struct nfs4_ff_layout_ds {
	struct nfs4_deviceid_node	id_node;
	u32				ds_versions_cnt;
	struct nfs4_ff_ds_version	*ds_versions;
	struct nfs4_pnfs_ds		*ds;
};

struct nfs4_ff_layout_ds_err {
	struct list_head		list; /* linked in mirror error_list */
	u64				offset;
	u64				length;
	int				status;
	enum nfs_opnum4			opnum;
	nfs4_stateid			stateid;
	struct nfs4_deviceid		deviceid;
};

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
struct nfs4_ff_io_stat {
	__u64				ops_requested;
	__u64				bytes_requested;
	__u64				ops_completed;
	__u64				bytes_completed;
	__u64				bytes_not_delivered;
	ktime_t				total_busy_time;
	ktime_t				aggregate_completion_time;
};

struct nfs4_ff_busy_timer {
	ktime_t start_time;
	atomic_t n_ops;
};

struct nfs4_ff_layoutstat {
	struct nfs4_ff_io_stat io_stat;
	struct nfs4_ff_busy_timer busy_timer;
};

74
struct nfs4_ff_layout_mirror {
75 76
	struct pnfs_layout_hdr		*layout;
	struct list_head		mirrors;
77 78
	u32				ds_count;
	u32				efficiency;
79
	struct nfs4_deviceid		devid;
80 81 82 83
	struct nfs4_ff_layout_ds	*mirror_ds;
	u32				fh_versions_cnt;
	struct nfs_fh			*fh_versions;
	nfs4_stateid			stateid;
84 85
	struct rpc_cred	__rcu		*ro_cred;
	struct rpc_cred	__rcu		*rw_cred;
86
	refcount_t			ref;
87
	spinlock_t			lock;
88
	unsigned long			flags;
89 90
	struct nfs4_ff_layoutstat	read_stat;
	struct nfs4_ff_layoutstat	write_stat;
91
	ktime_t				start_time;
92
	u32				report_interval;
93 94
};

95 96
#define NFS4_FF_MIRROR_STAT_AVAIL	(0)

97 98 99
struct nfs4_ff_layout_segment {
	struct pnfs_layout_segment	generic_hdr;
	u64				stripe_unit;
100
	u32				flags;
101 102 103 104 105 106 107
	u32				mirror_array_cnt;
	struct nfs4_ff_layout_mirror	**mirror_array;
};

struct nfs4_flexfile_layout {
	struct pnfs_layout_hdr generic_hdr;
	struct pnfs_ds_commit_info commit_info;
108
	struct list_head	mirrors;
109
	struct list_head	error_list; /* nfs4_ff_layout_ds_err */
110
	ktime_t			last_report_time; /* Layoutstat report times */
111 112
};

113 114
struct nfs4_flexfile_layoutreturn_args {
	struct list_head errors;
115
	struct nfs42_layoutstat_devinfo devinfo[FF_LAYOUTSTATS_MAXDEV];
116
	unsigned int num_errors;
117
	unsigned int num_dev;
118
	struct page *pages[1];
119 120
};

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
static inline struct nfs4_flexfile_layout *
FF_LAYOUT_FROM_HDR(struct pnfs_layout_hdr *lo)
{
	return container_of(lo, struct nfs4_flexfile_layout, generic_hdr);
}

static inline struct nfs4_ff_layout_segment *
FF_LAYOUT_LSEG(struct pnfs_layout_segment *lseg)
{
	return container_of(lseg,
			    struct nfs4_ff_layout_segment,
			    generic_hdr);
}

static inline struct nfs4_deviceid_node *
FF_LAYOUT_DEVID_NODE(struct pnfs_layout_segment *lseg, u32 idx)
{
	if (idx >= FF_LAYOUT_LSEG(lseg)->mirror_array_cnt ||
	    FF_LAYOUT_LSEG(lseg)->mirror_array[idx] == NULL ||
	    FF_LAYOUT_LSEG(lseg)->mirror_array[idx]->mirror_ds == NULL)
		return NULL;
	return &FF_LAYOUT_LSEG(lseg)->mirror_array[idx]->mirror_ds->id_node;
}

static inline struct nfs4_ff_layout_ds *
FF_LAYOUT_MIRROR_DS(struct nfs4_deviceid_node *node)
{
	return container_of(node, struct nfs4_ff_layout_ds, id_node);
}

static inline struct nfs4_ff_layout_mirror *
FF_LAYOUT_COMP(struct pnfs_layout_segment *lseg, u32 idx)
{
	if (idx >= FF_LAYOUT_LSEG(lseg)->mirror_array_cnt)
		return NULL;
	return FF_LAYOUT_LSEG(lseg)->mirror_array[idx];
}

static inline u32
FF_LAYOUT_MIRROR_COUNT(struct pnfs_layout_segment *lseg)
{
	return FF_LAYOUT_LSEG(lseg)->mirror_array_cnt;
}

165 166 167 168 169 170
static inline bool
ff_layout_no_fallback_to_mds(struct pnfs_layout_segment *lseg)
{
	return FF_LAYOUT_LSEG(lseg)->flags & FF_FLAGS_NO_IO_THRU_MDS;
}

171 172 173 174 175 176
static inline bool
ff_layout_no_read_on_rw(struct pnfs_layout_segment *lseg)
{
	return FF_LAYOUT_LSEG(lseg)->flags & FF_FLAGS_NO_READ_IO;
}

177 178 179
static inline bool
ff_layout_test_devid_unavailable(struct nfs4_deviceid_node *node)
{
180 181 182 183 184 185 186 187 188 189 190 191 192
	/*
	 * Flexfiles should never mark a DS unavailable, but if it does
	 * print a (ratelimited) warning as this can affect performance.
	 */
	if (nfs4_test_deviceid_unavailable(node)) {
		u32 *p = (u32 *)node->deviceid.data;

		pr_warn_ratelimited("NFS: flexfiles layout referencing an "
				"unavailable device [%x%x%x%x]\n",
				p[0], p[1], p[2], p[3]);
		return true;
	}
	return false;
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
}

static inline int
nfs4_ff_layout_ds_version(struct pnfs_layout_segment *lseg, u32 ds_idx)
{
	return FF_LAYOUT_COMP(lseg, ds_idx)->mirror_ds->ds_versions[0].version;
}

struct nfs4_ff_layout_ds *
nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
			    gfp_t gfp_flags);
void nfs4_ff_layout_put_deviceid(struct nfs4_ff_layout_ds *mirror_ds);
void nfs4_ff_layout_free_deviceid(struct nfs4_ff_layout_ds *mirror_ds);
int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
			     struct nfs4_ff_layout_mirror *mirror, u64 offset,
			     u64 length, int status, enum nfs_opnum4 opnum,
			     gfp_t gfp_flags);
210 211 212 213 214 215
int ff_layout_encode_ds_ioerr(struct xdr_stream *xdr, const struct list_head *head);
void ff_layout_free_ds_ioerr(struct list_head *head);
unsigned int ff_layout_fetch_ds_ioerr(struct pnfs_layout_hdr *lo,
		const struct pnfs_layout_range *range,
		struct list_head *head,
		unsigned int maxnum);
216 217 218 219 220 221 222 223 224 225 226 227 228 229
struct nfs_fh *
nfs4_ff_layout_select_ds_fh(struct pnfs_layout_segment *lseg, u32 mirror_idx);

struct nfs4_pnfs_ds *
nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
			  bool fail_return);

struct rpc_clnt *
nfs4_ff_find_or_create_ds_client(struct pnfs_layout_segment *lseg,
				 u32 ds_idx,
				 struct nfs_client *ds_clp,
				 struct inode *inode);
struct rpc_cred *ff_layout_get_ds_cred(struct pnfs_layout_segment *lseg,
				       u32 ds_idx, struct rpc_cred *mdscred);
230
bool ff_layout_avoid_mds_available_ds(struct pnfs_layout_segment *lseg);
231 232
bool ff_layout_avoid_read_on_rw(struct pnfs_layout_segment *lseg);

233
#endif /* FS_NFS_NFS4FLEXFILELAYOUT_H */