Whamcloud - gitweb
9ae5790f676ffd6d37da970273d73fa209388be4
[fs/lustre-release.git] / lustre / include / linux / lustre_fsfilt.h
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/include/linux/lustre_fsfilt.h
37  *
38  * Filesystem interface helper.
39  */
40
41 #ifndef _LINUX_LUSTRE_FSFILT_H
42 #define _LINUX_LUSTRE_FSFILT_H
43
44 #ifndef _LUSTRE_FSFILT_H
45 #error Do not #include this file directly. #include <lustre_fsfilt.h> instead
46 #endif
47
48 #ifdef __KERNEL__
49
50 #include <obd.h>
51 #include <obd_class.h>
52
53 typedef void (*fsfilt_cb_t)(struct obd_device *obd, __u64 last_rcvd,
54                             void *data, int error);
55
56 struct fsfilt_objinfo {
57         struct dentry *fso_dentry;
58         int fso_bufcnt;
59 };
60
61 struct fsfilt_fid {
62         __u32 ino;
63         __u32 gen;
64 };
65
66 struct lustre_dquot;
67 struct fsfilt_operations {
68         cfs_list_t fs_list;
69         cfs_module_t *fs_owner;
70         char   *fs_type;
71         char   *(* fs_getlabel)(struct super_block *sb);
72         int     (* fs_setlabel)(struct super_block *sb, char *label);
73         char   *(* fs_uuid)(struct super_block *sb);
74         void   *(* fs_start)(struct inode *inode, int op, void *desc_private,
75                              int logs);
76         void   *(* fs_brw_start)(int objcount, struct fsfilt_objinfo *fso,
77                                  int niocount, struct niobuf_local *nb,
78                                  void *desc_private, int logs);
79         int     (* fs_extend)(struct inode *inode, unsigned nblocks, void *h);
80         int     (* fs_commit)(struct inode *inode, void *handle,int force_sync);
81         int     (* fs_commit_async)(struct inode *inode, void *handle,
82                                         void **wait_handle);
83         int     (* fs_commit_wait)(struct inode *inode, void *handle);
84         int     (* fs_setattr)(struct dentry *dentry, void *handle,
85                                struct iattr *iattr, int do_trunc);
86         int     (* fs_iocontrol)(struct inode *inode, struct file *file,
87                                  unsigned int cmd, unsigned long arg);
88         int     (* fs_set_md)(struct inode *inode, void *handle, void *md,
89                               int size, const char *name);
90         int     (* fs_get_md)(struct inode *inode, void *md, int size,
91                               const char *name);
92         /*
93          * this method is needed to make IO operation fsfilt nature depend.
94          *
95          * This operation maybe synchronous or asynchronous.
96          *
97          * Return convention: positive number of bytes written (synchronously)
98          * on success. Negative errno value on failure. Zero if asynchronous
99          * IO was submitted successfully.
100          *
101          */
102         int     (* fs_send_bio)(int rw, struct inode *inode, struct bio *bio);
103         ssize_t (* fs_readpage)(struct file *file, char *buf, size_t count,
104                                 loff_t *offset);
105         int     (* fs_add_journal_cb)(struct obd_device *obd, __u64 last_rcvd,
106                                       void *handle, fsfilt_cb_t cb_func,
107                                       void *cb_data);
108         int     (* fs_statfs)(struct super_block *sb, struct obd_statfs *osfs);
109         int     (* fs_sync)(struct super_block *sb);
110         int     (* fs_map_inode_pages)(struct inode *inode, struct page **page,
111                                        int pages, unsigned long *blocks,
112                                        int *created, int create,
113                                        struct mutex *sem);
114         int     (* fs_write_record)(struct file *, void *, int size, loff_t *,
115                                     int force_sync);
116         int     (* fs_read_record)(struct file *, void *, int size, loff_t *);
117         int     (* fs_setup)(struct super_block *sb);
118         int     (* fs_get_op_len)(int, struct fsfilt_objinfo *, int);
119         __u64   (* fs_get_version) (struct inode *inode);
120         __u64   (* fs_set_version) (struct inode *inode, __u64 new_version);
121         lvfs_sbdev_type (* fs_journal_sbdev)(struct super_block *sb);
122         struct dentry  *(* fs_fid2dentry)(struct vfsmount *mnt,
123                                           struct fsfilt_fid *fid,
124                                           int ignore_gen);
125 };
126
127 extern int fsfilt_register_ops(struct fsfilt_operations *fs_ops);
128 extern void fsfilt_unregister_ops(struct fsfilt_operations *fs_ops);
129 extern struct fsfilt_operations *fsfilt_get_ops(const char *type);
130 extern void fsfilt_put_ops(struct fsfilt_operations *fs_ops);
131
132 static inline char *fsfilt_get_label(struct obd_device *obd,
133                                      struct super_block *sb)
134 {
135         if (obd->obd_fsops->fs_getlabel == NULL)
136                 return NULL;
137         if (obd->obd_fsops->fs_getlabel(sb)[0] == '\0')
138                 return NULL;
139
140         return obd->obd_fsops->fs_getlabel(sb);
141 }
142
143 static inline int fsfilt_set_label(struct obd_device *obd,
144                                    struct super_block *sb, char *label)
145 {
146         if (obd->obd_fsops->fs_setlabel == NULL)
147                 return -ENOSYS;
148         return (obd->obd_fsops->fs_setlabel(sb, label));
149 }
150
151 static inline __u8 *fsfilt_uuid(struct obd_device *obd, struct super_block *sb)
152 {
153         if (obd->obd_fsops->fs_uuid == NULL)
154                 return NULL;
155
156         return obd->obd_fsops->fs_uuid(sb);
157 }
158
159 static inline lvfs_sbdev_type fsfilt_journal_sbdev(struct obd_device *obd,
160                                                    struct super_block *sb)
161 {
162         if (obd && obd->obd_fsops && obd->obd_fsops->fs_journal_sbdev)
163                 return obd->obd_fsops->fs_journal_sbdev(sb);
164         return (lvfs_sbdev_type)0;
165 }
166
167 #define FSFILT_OP_UNLINK                1
168 #define FSFILT_OP_RMDIR                 2
169 #define FSFILT_OP_RENAME                3
170 #define FSFILT_OP_CREATE                4
171 #define FSFILT_OP_MKDIR                 5
172 #define FSFILT_OP_SYMLINK               6
173 #define FSFILT_OP_MKNOD                 7
174 #define FSFILT_OP_SETATTR               8
175 #define FSFILT_OP_LINK                  9
176 #define FSFILT_OP_CANCEL_UNLINK         10
177 #define FSFILT_OP_NOOP                  15
178 #define FSFILT_OP_UNLINK_PARTIAL_CHILD  21
179 #define FSFILT_OP_UNLINK_PARTIAL_PARENT 22
180 #define FSFILT_OP_CREATE_PARTIAL_CHILD  23
181
182 #define __fsfilt_check_slow(obd, start, msg)                              \
183 do {                                                                      \
184         if (cfs_time_before(jiffies, start + 15 * CFS_HZ))                \
185                 break;                                                    \
186         else if (cfs_time_before(jiffies, start + 30 * CFS_HZ))           \
187                 CDEBUG(D_VFSTRACE, "%s: slow %s %lus\n", obd->obd_name,   \
188                        msg, (jiffies-start) / CFS_HZ);                    \
189         else if (cfs_time_before(jiffies, start + DISK_TIMEOUT * CFS_HZ)) \
190                 CWARN("%s: slow %s %lus\n", obd->obd_name, msg,           \
191                       (jiffies - start) / CFS_HZ);                        \
192         else                                                              \
193                 CERROR("%s: slow %s %lus\n", obd->obd_name, msg,          \
194                        (jiffies - start) / CFS_HZ);                       \
195 } while (0)
196
197 #define fsfilt_check_slow(obd, start, msg)              \
198 do {                                                    \
199         __fsfilt_check_slow(obd, start, msg);           \
200         start = jiffies;                                \
201 } while (0)
202
203 static inline void *fsfilt_start_log(struct obd_device *obd,
204                                      struct inode *inode, int op,
205                                      struct obd_trans_info *oti, int logs)
206 {
207         unsigned long now = jiffies;
208         void *parent_handle = oti ? oti->oti_handle : NULL;
209         void *handle;
210
211         handle = obd->obd_fsops->fs_start(inode, op, parent_handle, logs);
212         CDEBUG(D_INFO, "started handle %p (%p)\n", handle, parent_handle);
213
214         if (oti != NULL) {
215                 if (parent_handle == NULL) {
216                         oti->oti_handle = handle;
217                 } else if (handle != parent_handle) {
218                         CERROR("mismatch: parent %p, handle %p, oti %p\n",
219                                parent_handle, handle, oti);
220                         LBUG();
221                 }
222         }
223         fsfilt_check_slow(obd, now, "journal start");
224         return handle;
225 }
226
227 static inline void *fsfilt_start(struct obd_device *obd, struct inode *inode,
228                                  int op, struct obd_trans_info *oti)
229 {
230         return fsfilt_start_log(obd, inode, op, oti, 0);
231 }
232
233 static inline void *fsfilt_brw_start_log(struct obd_device *obd, int objcount,
234                                          struct fsfilt_objinfo *fso,
235                                          int niocount, struct niobuf_local *nb,
236                                          struct obd_trans_info *oti, int logs)
237 {
238         unsigned long now = jiffies;
239         void *parent_handle = oti ? oti->oti_handle : NULL;
240         void *handle;
241
242         handle = obd->obd_fsops->fs_brw_start(objcount, fso, niocount, nb,
243                                               parent_handle, logs);
244         CDEBUG(D_INFO, "started handle %p (%p)\n", handle, parent_handle);
245
246         if (oti != NULL) {
247                 if (parent_handle == NULL) {
248                         oti->oti_handle = handle;
249                 } else if (handle != parent_handle) {
250                         CERROR("mismatch: parent %p, handle %p, oti %p\n",
251                                parent_handle, handle, oti);
252                         LBUG();
253                 }
254         }
255         fsfilt_check_slow(obd, now, "journal start");
256
257         return handle;
258 }
259
260 static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount,
261                                      struct fsfilt_objinfo *fso, int niocount,
262                                      struct niobuf_local *nb,
263                                      struct obd_trans_info *oti)
264 {
265         return fsfilt_brw_start_log(obd, objcount, fso, niocount, nb, oti, 0);
266 }
267
268 static inline int fsfilt_extend(struct obd_device *obd, struct inode *inode,
269                                 unsigned int nblocks, void *handle)
270 {
271         unsigned long now = jiffies;
272         int rc = obd->obd_fsops->fs_extend(inode, nblocks, handle);
273         CDEBUG(D_INFO, "extending handle %p with %u blocks\n", handle, nblocks);
274
275         fsfilt_check_slow(obd, now, "journal extend");
276
277         return rc;
278 }
279
280 static inline int fsfilt_commit(struct obd_device *obd, struct inode *inode,
281                                 void *handle, int force_sync)
282 {
283         unsigned long now = jiffies;
284         int rc = obd->obd_fsops->fs_commit(inode, handle, force_sync);
285         CDEBUG(D_INFO, "committing handle %p\n", handle);
286
287         fsfilt_check_slow(obd, now, "journal start");
288
289         return rc;
290 }
291
292 static inline int fsfilt_commit_async(struct obd_device *obd,
293                                       struct inode *inode, void *handle,
294                                       void **wait_handle)
295 {
296         unsigned long now = jiffies;
297         int rc = obd->obd_fsops->fs_commit_async(inode, handle, wait_handle);
298
299         CDEBUG(D_INFO, "committing handle %p (async)\n", *wait_handle);
300         fsfilt_check_slow(obd, now, "journal start");
301
302         return rc;
303 }
304
305 static inline int fsfilt_commit_wait(struct obd_device *obd,
306                                      struct inode *inode, void *handle)
307 {
308         unsigned long now = jiffies;
309         int rc = obd->obd_fsops->fs_commit_wait(inode, handle);
310         CDEBUG(D_INFO, "waiting for completion %p\n", handle);
311         fsfilt_check_slow(obd, now, "journal start");
312         return rc;
313 }
314
315 static inline int fsfilt_setattr(struct obd_device *obd, struct dentry *dentry,
316                                  void *handle, struct iattr *iattr,int do_trunc)
317 {
318         unsigned long now = jiffies;
319         int rc;
320         rc = obd->obd_fsops->fs_setattr(dentry, handle, iattr, do_trunc);
321         fsfilt_check_slow(obd, now, "setattr");
322         return rc;
323 }
324
325 static inline int fsfilt_iocontrol(struct obd_device *obd, struct dentry *dentry,
326                                    unsigned int cmd, unsigned long arg)
327 {
328         struct file *dummy_file = NULL;
329         int ret;
330
331         OBD_ALLOC_PTR(dummy_file);
332         if (!dummy_file)
333                 return(-ENOMEM);
334
335         dummy_file->f_dentry = dentry;
336         dummy_file->f_vfsmnt = obd->u.obt.obt_vfsmnt;
337
338         ret = obd->obd_fsops->fs_iocontrol(dentry->d_inode, dummy_file, cmd,
339                                            arg);
340
341         OBD_FREE_PTR(dummy_file);
342         return ret;
343 }
344
345 static inline int fsfilt_set_md(struct obd_device *obd, struct inode *inode,
346                                 void *handle, void *md, int size,
347                                 const char *name)
348 {
349         return obd->obd_fsops->fs_set_md(inode, handle, md, size, name);
350 }
351
352 static inline int fsfilt_get_md(struct obd_device *obd, struct inode *inode,
353                                 void *md, int size, const char *name)
354 {
355         return obd->obd_fsops->fs_get_md(inode, md, size, name);
356 }
357
358 static inline int fsfilt_send_bio(int rw, struct obd_device *obd,
359                                   struct inode *inode, void *bio)
360 {
361         LASSERTF(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ, "%x\n", rw);
362
363         if (rw == OBD_BRW_READ)
364                 return obd->obd_fsops->fs_send_bio(READ, inode, bio);
365         return obd->obd_fsops->fs_send_bio(WRITE, inode, bio);
366 }
367
368 static inline ssize_t fsfilt_readpage(struct obd_device *obd,
369                                       struct file *file, char *buf,
370                                       size_t count, loff_t *offset)
371 {
372         return obd->obd_fsops->fs_readpage(file, buf, count, offset);
373 }
374
375 static inline int fsfilt_add_journal_cb(struct obd_device *obd, __u64 last_rcvd,
376                                         void *handle, fsfilt_cb_t cb_func,
377                                         void *cb_data)
378 {
379         return obd->obd_fsops->fs_add_journal_cb(obd, last_rcvd,
380                                                  handle, cb_func, cb_data);
381 }
382
383 /* very similar to obd_statfs(), but caller already holds obd_osfs_lock */
384 static inline int fsfilt_statfs(struct obd_device *obd, struct super_block *sb,
385                                 __u64 max_age)
386 {
387         int rc = 0;
388
389         CDEBUG(D_SUPER, "osfs "LPU64", max_age "LPU64"\n",
390                 obd->obd_osfs_age, max_age);
391         if (cfs_time_before_64(obd->obd_osfs_age, max_age)) {
392                 rc = obd->obd_fsops->fs_statfs(sb, &obd->obd_osfs);
393                 if (rc == 0) /* N.B. statfs can't really fail */
394                         obd->obd_osfs_age = cfs_time_current_64();
395         } else {
396                 CDEBUG(D_SUPER, "using cached obd_statfs data\n");
397         }
398
399         return rc;
400 }
401
402 static inline int fsfilt_sync(struct obd_device *obd, struct super_block *sb)
403 {
404         return obd->obd_fsops->fs_sync(sb);
405 }
406
407 static inline int fsfilt_map_inode_pages(struct obd_device *obd,
408                                          struct inode *inode,
409                                          struct page **page, int pages,
410                                          unsigned long *blocks, int *created,
411                                          int create, struct mutex *mutex)
412 {
413         return obd->obd_fsops->fs_map_inode_pages(inode, page, pages, blocks,
414                                                   created, create, mutex);
415 }
416
417 static inline int fsfilt_read_record(struct obd_device *obd, struct file *file,
418                                      void *buf, loff_t size, loff_t *offs)
419 {
420         return obd->obd_fsops->fs_read_record(file, buf, size, offs);
421 }
422
423 static inline int fsfilt_write_record(struct obd_device *obd, struct file *file,
424                                       void *buf, loff_t size, loff_t *offs,
425                                       int force_sync)
426 {
427         return obd->obd_fsops->fs_write_record(file, buf, size,offs,force_sync);
428 }
429
430 static inline int fsfilt_setup(struct obd_device *obd, struct super_block *fs)
431 {
432         if (obd->obd_fsops->fs_setup)
433                 return obd->obd_fsops->fs_setup(fs);
434         return 0;
435 }
436
437 static inline __u64 fsfilt_set_version(struct obd_device *obd,
438                                       struct inode *inode, __u64 new_version)
439 {
440         if (obd->obd_fsops->fs_set_version)
441                 return obd->obd_fsops->fs_set_version(inode, new_version);
442         return -EOPNOTSUPP;
443 }
444
445 static inline __u64 fsfilt_get_version(struct obd_device *obd,
446                                        struct inode *inode)
447 {
448         if (obd->obd_fsops->fs_get_version)
449                 return obd->obd_fsops->fs_get_version(inode);
450         return -EOPNOTSUPP;
451 }
452
453 static inline struct dentry *fsfilt_fid2dentry(struct obd_device *obd,
454                                                struct vfsmount *mnt,
455                                                struct fsfilt_fid *fid,
456                                                int ignore_gen)
457 {
458         if (obd->obd_fsops->fs_fid2dentry)
459                 return obd->obd_fsops->fs_fid2dentry(mnt, fid, ignore_gen);
460         return ERR_PTR(-EOPNOTSUPP);
461 }
462
463 #endif /* __KERNEL__ */
464
465 #endif