summaryrefslogtreecommitdiff
path: root/fs/nfs/flexfilelayout/flexfilelayout.h
blob: dd353bb7dc0a01ddb76eabdca99a77b75193fe82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
 * 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

#define FF_FLAGS_NO_LAYOUTCOMMIT 1
#define FF_FLAGS_NO_IO_THRU_MDS 2

#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

/* LAYOUTSTATS report interval in ms */
#define FF_LAYOUTSTATS_REPORT_INTERVAL (60000L)

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;
};

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;
};

struct nfs4_ff_layout_mirror {
	struct pnfs_layout_hdr		*layout;
	struct list_head		mirrors;
	u32				ds_count;
	u32				efficiency;
	struct nfs4_ff_layout_ds	*mirror_ds;
	u32				fh_versions_cnt;
	struct nfs_fh			*fh_versions;
	nfs4_stateid			stateid;
	u32				uid;
	u32				gid;
	struct rpc_cred			*cred;
	atomic_t			ref;
	spinlock_t			lock;
	struct nfs4_ff_layoutstat	read_stat;
	struct nfs4_ff_layoutstat	write_stat;
	ktime_t				start_time;
	ktime_t				last_report_time;
	u32				report_interval;
};

struct nfs4_ff_layout_segment {
	struct pnfs_layout_segment	generic_hdr;
	u64				stripe_unit;
	u32				flags;
	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;
	struct list_head	mirrors;
	struct list_head	error_list; /* nfs4_ff_layout_ds_err */
};

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;
}

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;
}

static inline bool
ff_layout_test_devid_unavailable(struct nfs4_deviceid_node *node)
{
	return nfs4_test_deviceid_unavailable(node);
}

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);
int ff_layout_encode_ds_ioerr(struct nfs4_flexfile_layout *flo,
			      struct xdr_stream *xdr, int *count,
			      const struct pnfs_layout_range *range);
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);
bool ff_layout_has_available_ds(struct pnfs_layout_segment *lseg);
#endif /* FS_NFS_NFS4FLEXFILELAYOUT_H */