aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/lustre/lustre/llite/vvp_internal.h
blob: 5802da81cd0e34559f163503d15b95a72d4158d4 (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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
 * GPL HEADER START
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 only,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License version 2 for more details (a copy is included
 * in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License
 * version 2 along with this program; If not, see
 * http://www.gnu.org/licenses/gpl-2.0.html
 *
 * GPL HEADER END
 */
/*
 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
 * Use is subject to license terms.
 *
 * Copyright (c) 2013, 2015, Intel Corporation.
 */
/*
 * This file is part of Lustre, http://www.lustre.org/
 * Lustre is a trademark of Sun Microsystems, Inc.
 *
 * Internal definitions for VVP layer.
 *
 *   Author: Nikita Danilov <nikita.danilov@sun.com>
 */

#ifndef VVP_INTERNAL_H
#define VVP_INTERNAL_H

#include "../include/lustre/lustre_idl.h"
#include "../include/cl_object.h"

enum obd_notify_event;
struct inode;
struct lov_stripe_md;
struct lustre_md;
struct obd_capa;
struct obd_device;
struct obd_export;
struct page;

/* specific architecture can implement only part of this list */
enum vvp_io_subtype {
	/** normal IO */
	IO_NORMAL,
	/** io started from splice_{read|write} */
	IO_SPLICE
};

/**
 * IO state private to IO state private to VVP layer.
 */
struct vvp_io {
	/** super class */
	struct cl_io_slice     vui_cl;
	struct cl_io_lock_link vui_link;
	/**
	 * I/O vector information to or from which read/write is going.
	 */
	struct iov_iter *vui_iter;
	/**
	 * Total size for the left IO.
	 */
	size_t vui_tot_count;

	union {
		struct vvp_fault_io {
			/**
			 * Inode modification time that is checked across DLM
			 * lock request.
			 */
			time64_t	    ft_mtime;
			struct vm_area_struct *ft_vma;
			/**
			 *  locked page returned from vvp_io
			 */
			struct page	    *ft_vmpage;
			/**
			 * kernel fault info
			 */
			struct vm_fault *ft_vmf;
			/**
			 * fault API used bitflags for return code.
			 */
			unsigned int    ft_flags;
			/**
			 * check that flags are from filemap_fault
			 */
			bool		ft_flags_valid;
		} fault;
		struct {
			struct pipe_inode_info	*vui_pipe;
			unsigned int		 vui_flags;
		} splice;
		struct {
			struct cl_page_list vui_queue;
			unsigned long vui_written;
			int vui_from;
			int vui_to;
		} write;
	} u;

	enum vvp_io_subtype	vui_io_subtype;

	/**
	 * Layout version when this IO is initialized
	 */
	__u32			vui_layout_gen;
	/**
	 * File descriptor against which IO is done.
	 */
	struct ll_file_data	*vui_fd;
	struct kiocb		*vui_iocb;

	/* Readahead state. */
	pgoff_t	vui_ra_start;
	pgoff_t	vui_ra_count;
	/* Set when vui_ra_{start,count} have been initialized. */
	bool		vui_ra_valid;
};

extern struct lu_device_type vvp_device_type;

extern struct lu_context_key vvp_session_key;
extern struct lu_context_key vvp_thread_key;

extern struct kmem_cache *vvp_lock_kmem;
extern struct kmem_cache *vvp_object_kmem;
extern struct kmem_cache *vvp_req_kmem;

struct vvp_thread_info {
	struct cl_lock		vti_lock;
	struct cl_lock_descr	vti_descr;
	struct cl_io		vti_io;
	struct cl_attr		vti_attr;
};

static inline struct vvp_thread_info *vvp_env_info(const struct lu_env *env)
{
	struct vvp_thread_info      *vti;

	vti = lu_context_key_get(&env->le_ctx, &vvp_thread_key);
	LASSERT(vti);

	return vti;
}

static inline struct cl_lock *vvp_env_lock(const struct lu_env *env)
{
	struct cl_lock *lock = &vvp_env_info(env)->vti_lock;

	memset(lock, 0, sizeof(*lock));
	return lock;
}

static inline struct cl_attr *vvp_env_thread_attr(const struct lu_env *env)
{
	struct cl_attr *attr = &vvp_env_info(env)->vti_attr;

	memset(attr, 0, sizeof(*attr));

	return attr;
}

static inline struct cl_io *vvp_env_thread_io(const struct lu_env *env)
{
	struct cl_io *io = &vvp_env_info(env)->vti_io;

	memset(io, 0, sizeof(*io));

	return io;
}

struct vvp_session {
	struct vvp_io cs_ios;
};

static inline struct vvp_session *vvp_env_session(const struct lu_env *env)
{
	struct vvp_session *ses;

	ses = lu_context_key_get(env->le_ses, &vvp_session_key);
	LASSERT(ses);

	return ses;
}

static inline struct vvp_io *vvp_env_io(const struct lu_env *env)
{
	return &vvp_env_session(env)->cs_ios;
}

/**
 * ccc-private object state.
 */
struct vvp_object {
	struct cl_object_header vob_header;
	struct cl_object        vob_cl;
	struct inode           *vob_inode;

	/**
	 * A list of dirty pages pending IO in the cache. Used by
	 * SOM. Protected by ll_inode_info::lli_lock.
	 *
	 * \see vvp_page::vpg_pending_linkage
	 */
	struct list_head	vob_pending_list;

	/**
	 * Number of transient pages.  This is no longer protected by i_sem,
	 * and needs to be atomic.  This is not actually used for anything,
	 * and can probably be removed.
	 */
	atomic_t		vob_transient_pages;

	/**
	 * Number of outstanding mmaps on this file.
	 *
	 * \see ll_vm_open(), ll_vm_close().
	 */
	atomic_t                vob_mmap_cnt;

	/**
	 * various flags
	 * vob_discard_page_warned
	 *     if pages belonging to this object are discarded when a client
	 * is evicted, some debug info will be printed, this flag will be set
	 * during processing the first discarded page, then avoid flooding
	 * debug message for lots of discarded pages.
	 *
	 * \see ll_dirty_page_discard_warn.
	 */
	unsigned int		vob_discard_page_warned:1;
};

/**
 * VVP-private page state.
 */
struct vvp_page {
	struct cl_page_slice vpg_cl;
	unsigned int	vpg_defer_uptodate:1,
			vpg_ra_used:1,
			vpg_write_queued:1;
	/**
	 * Non-empty iff this page is already counted in
	 * vvp_object::vob_pending_list. This list is only used as a flag,
	 * that is, never iterated through, only checked for list_empty(), but
	 * having a list is useful for debugging.
	 */
	struct list_head	   vpg_pending_linkage;
	/** VM page */
	struct page	  *vpg_page;
};

static inline struct vvp_page *cl2vvp_page(const struct cl_page_slice *slice)
{
	return container_of(slice, struct vvp_page, vpg_cl);
}

static inline pgoff_t vvp_index(struct vvp_page *vvp)
{
	return vvp->vpg_cl.cpl_index;
}

struct vvp_device {
	struct cl_device    vdv_cl;
	struct super_block *vdv_sb;
	struct cl_device   *vdv_next;
};

struct vvp_lock {
	struct cl_lock_slice vlk_cl;
};

struct vvp_req {
	struct cl_req_slice  vrq_cl;
};

void *ccc_key_init(const struct lu_context *ctx,
		   struct lu_context_key *key);
void ccc_key_fini(const struct lu_context *ctx,
		  struct lu_context_key *key, void *data);

void ccc_umount(const struct lu_env *env, struct cl_device *dev);

static inline struct lu_device *vvp2lu_dev(struct vvp_device *vdv)
{
	return &vdv->vdv_cl.cd_lu_dev;
}

static inline struct vvp_device *lu2vvp_dev(const struct lu_device *d)
{
	return container_of0(d, struct vvp_device, vdv_cl.cd_lu_dev);
}

static inline struct vvp_device *cl2vvp_dev(const struct cl_device *d)
{
	return container_of0(d, struct vvp_device, vdv_cl);
}

static inline struct vvp_object *cl2vvp(const struct cl_object *obj)
{
	return container_of0(obj, struct vvp_object, vob_cl);
}

static inline struct vvp_object *lu2vvp(const struct lu_object *obj)
{
	return container_of0(obj, struct vvp_object, vob_cl.co_lu);
}

static inline struct inode *vvp_object_inode(const struct cl_object *obj)
{
	return cl2vvp(obj)->vob_inode;
}

int vvp_object_invariant(const struct cl_object *obj);
struct vvp_object *cl_inode2vvp(struct inode *inode);

static inline struct page *cl2vm_page(const struct cl_page_slice *slice)
{
	return cl2vvp_page(slice)->vpg_page;
}

static inline struct vvp_lock *cl2vvp_lock(const struct cl_lock_slice *slice)
{
	return container_of(slice, struct vvp_lock, vlk_cl);
}

# define CLOBINVRNT(env, clob, expr)					\
	((void)sizeof(env), (void)sizeof(clob), (void)sizeof(!!(expr)))

/**
 * New interfaces to get and put lov_stripe_md from lov layer. This violates
 * layering because lov_stripe_md is supposed to be a private data in lov.
 *
 * NB: If you find you have to use these interfaces for your new code, please
 * think about it again. These interfaces may be removed in the future for
 * better layering.
 */
struct lov_stripe_md *lov_lsm_get(struct cl_object *clobj);
void lov_lsm_put(struct cl_object *clobj, struct lov_stripe_md *lsm);
int lov_read_and_clear_async_rc(struct cl_object *clob);

struct lov_stripe_md *ccc_inode_lsm_get(struct inode *inode);
void ccc_inode_lsm_put(struct inode *inode, struct lov_stripe_md *lsm);

int vvp_io_init(const struct lu_env *env, struct cl_object *obj,
		struct cl_io *io);
int vvp_io_write_commit(const struct lu_env *env, struct cl_io *io);
int vvp_lock_init(const struct lu_env *env, struct cl_object *obj,
		  struct cl_lock *lock, const struct cl_io *io);
int vvp_page_init(const struct lu_env *env, struct cl_object *obj,
		  struct cl_page *page, pgoff_t index);
int vvp_req_init(const struct lu_env *env, struct cl_device *dev,
		 struct cl_req *req);
struct lu_object *vvp_object_alloc(const struct lu_env *env,
				   const struct lu_object_header *hdr,
				   struct lu_device *dev);

int vvp_global_init(void);
void vvp_global_fini(void);

extern const struct file_operations vvp_dump_pgcache_file_ops;

#endif /* VVP_INTERNAL_H */