s3: Fix a few "warning: ISO C90 forbids mixed declarations and code"
[kai/samba.git] / source3 / modules / vfs_time_audit.c
1 /*
2  * Time auditing VFS module for samba.  Log time taken for VFS call to syslog
3  * facility.
4  *
5  * Copyright (C) Abhidnya Chirmule <achirmul@in.ibm.com> 2009
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22  * This module implements logging for time taken for all Samba VFS operations.
23  *
24  * vfs objects = time_audit
25  */
26
27
28 #include "includes.h"
29 #include "smbd/smbd.h"
30 #include "ntioctl.h"
31 #include "lib/util/tevent_unix.h"
32
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_VFS
35
36 static double audit_timeout;
37
38 static void smb_time_audit_log(const char *syscallname, double elapsed)
39 {
40         DEBUG(0, ("WARNING: System call \"%s\" took unexpectedly long "
41                   "(%.2f seconds) -- Validate that file and storage "
42                   "subsystems are operating normally\n", syscallname,
43                   elapsed));
44 }
45
46 static int smb_time_audit_connect(vfs_handle_struct *handle,
47                                   const char *svc, const char *user)
48 {
49         int result;
50         struct timespec ts1,ts2;
51         double timediff;
52
53         if (!handle) {
54                 return -1;
55         }
56
57         clock_gettime_mono(&ts1);
58         result = SMB_VFS_NEXT_CONNECT(handle, svc, user);
59         clock_gettime_mono(&ts2);
60         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
61         if (timediff > audit_timeout) {
62                 smb_time_audit_log("connect", timediff);
63         }
64         return result;
65 }
66
67 static void smb_time_audit_disconnect(vfs_handle_struct *handle)
68 {
69         struct timespec ts1,ts2;
70         double timediff;
71
72         clock_gettime_mono(&ts1);
73         SMB_VFS_NEXT_DISCONNECT(handle);
74         clock_gettime_mono(&ts2);
75         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
76
77         if (timediff > audit_timeout) {
78                 smb_time_audit_log("disconnect", timediff);
79         }
80 }
81
82 static uint64_t smb_time_audit_disk_free(vfs_handle_struct *handle,
83                                          const char *path,
84                                          bool small_query, uint64_t *bsize,
85                                          uint64_t *dfree, uint64_t *dsize)
86 {
87         uint64_t result;
88         struct timespec ts1,ts2;
89         double timediff;
90
91         clock_gettime_mono(&ts1);
92         result = SMB_VFS_NEXT_DISK_FREE(handle, path, small_query, bsize,
93                                         dfree, dsize);
94         clock_gettime_mono(&ts2);
95         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
96
97         /* Don't have a reasonable notion of failure here */
98         if (timediff > audit_timeout) {
99                 smb_time_audit_log("disk_free", timediff);
100         }
101
102         return result;
103 }
104
105 static int smb_time_audit_get_quota(struct vfs_handle_struct *handle,
106                                     enum SMB_QUOTA_TYPE qtype, unid_t id,
107                                     SMB_DISK_QUOTA *qt)
108 {
109         int result;
110         struct timespec ts1,ts2;
111         double timediff;
112
113         clock_gettime_mono(&ts1);
114         result = SMB_VFS_NEXT_GET_QUOTA(handle, qtype, id, qt);
115         clock_gettime_mono(&ts2);
116         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
117
118         if (timediff > audit_timeout) {
119                 smb_time_audit_log("get_quota", timediff);
120         }
121         return result;
122 }
123
124 static int smb_time_audit_set_quota(struct vfs_handle_struct *handle,
125                                     enum SMB_QUOTA_TYPE qtype, unid_t id,
126                                     SMB_DISK_QUOTA *qt)
127 {
128         int result;
129         struct timespec ts1,ts2;
130         double timediff;
131
132         clock_gettime_mono(&ts1);
133         result = SMB_VFS_NEXT_SET_QUOTA(handle, qtype, id, qt);
134         clock_gettime_mono(&ts2);
135         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
136
137         if (timediff > audit_timeout) {
138                 smb_time_audit_log("set_quota", timediff);
139         }
140
141         return result;
142 }
143
144 static int smb_time_audit_get_shadow_copy_data(struct vfs_handle_struct *handle,
145                                                struct files_struct *fsp,
146                                                struct shadow_copy_data *shadow_copy_data,
147                                                bool labels)
148 {
149         int result;
150         struct timespec ts1,ts2;
151         double timediff;
152
153         clock_gettime_mono(&ts1);
154         result = SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp,
155                                                    shadow_copy_data, labels);
156         clock_gettime_mono(&ts2);
157         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
158
159         if (timediff > audit_timeout) {
160                 smb_time_audit_log("get_shadow_copy_data", timediff);
161         }
162
163         return result;
164 }
165
166 static int smb_time_audit_statvfs(struct vfs_handle_struct *handle,
167                                   const char *path,
168                                   struct vfs_statvfs_struct *statbuf)
169 {
170         int result;
171         struct timespec ts1,ts2;
172         double timediff;
173
174         clock_gettime_mono(&ts1);
175         result = SMB_VFS_NEXT_STATVFS(handle, path, statbuf);
176         clock_gettime_mono(&ts2);
177         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
178
179         if (timediff > audit_timeout) {
180                 smb_time_audit_log("statvfs", timediff);
181         }
182
183         return result;
184 }
185
186 static uint32_t smb_time_audit_fs_capabilities(struct vfs_handle_struct *handle,
187                                                enum timestamp_set_resolution *p_ts_res)
188 {
189         uint32_t result;
190         struct timespec ts1,ts2;
191         double timediff;
192
193         clock_gettime_mono(&ts1);
194         result = SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res);
195         clock_gettime_mono(&ts2);
196         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
197
198         if (timediff > audit_timeout) {
199                 smb_time_audit_log("fs_capabilities", timediff);
200         }
201
202         return result;
203 }
204
205 static DIR *smb_time_audit_opendir(vfs_handle_struct *handle,
206                                               const char *fname,
207                                               const char *mask, uint32 attr)
208 {
209         DIR *result;
210         struct timespec ts1,ts2;
211         double timediff;
212
213         clock_gettime_mono(&ts1);
214         result = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
215         clock_gettime_mono(&ts2);
216         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
217
218         if (timediff > audit_timeout) {
219                 smb_time_audit_log("opendir", timediff);
220         }
221
222         return result;
223 }
224
225 static DIR *smb_time_audit_fdopendir(vfs_handle_struct *handle,
226                                               files_struct *fsp,
227                                               const char *mask, uint32 attr)
228 {
229         DIR *result;
230         struct timespec ts1,ts2;
231         double timediff;
232
233         clock_gettime_mono(&ts1);
234         result = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask, attr);
235         clock_gettime_mono(&ts2);
236         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
237
238         if (timediff > audit_timeout) {
239                 smb_time_audit_log("fdopendir", timediff);
240         }
241
242         return result;
243 }
244
245 static struct dirent *smb_time_audit_readdir(vfs_handle_struct *handle,
246                                                  DIR *dirp,
247                                                  SMB_STRUCT_STAT *sbuf)
248 {
249         struct dirent *result;
250         struct timespec ts1,ts2;
251         double timediff;
252
253         clock_gettime_mono(&ts1);
254         result = SMB_VFS_NEXT_READDIR(handle, dirp, sbuf);
255         clock_gettime_mono(&ts2);
256         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
257
258         if (timediff > audit_timeout) {
259                 smb_time_audit_log("readdir", timediff);
260         }
261
262         return result;
263 }
264
265 static void smb_time_audit_seekdir(vfs_handle_struct *handle,
266                                    DIR *dirp, long offset)
267 {
268         struct timespec ts1,ts2;
269         double timediff;
270
271         clock_gettime_mono(&ts1);
272         SMB_VFS_NEXT_SEEKDIR(handle, dirp, offset);
273         clock_gettime_mono(&ts2);
274         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
275
276         if (timediff > audit_timeout) {
277                 smb_time_audit_log("seekdir", timediff);
278         }
279
280 }
281
282 static long smb_time_audit_telldir(vfs_handle_struct *handle,
283                                    DIR *dirp)
284 {
285         long result;
286         struct timespec ts1,ts2;
287         double timediff;
288
289         clock_gettime_mono(&ts1);
290         result = SMB_VFS_NEXT_TELLDIR(handle, dirp);
291         clock_gettime_mono(&ts2);
292         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
293
294         if (timediff > audit_timeout) {
295                 smb_time_audit_log("telldir", timediff);
296         }
297
298         return result;
299 }
300
301 static void smb_time_audit_rewinddir(vfs_handle_struct *handle,
302                                      DIR *dirp)
303 {
304         struct timespec ts1,ts2;
305         double timediff;
306
307         clock_gettime_mono(&ts1);
308         SMB_VFS_NEXT_REWINDDIR(handle, dirp);
309         clock_gettime_mono(&ts2);
310         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
311
312         if (timediff > audit_timeout) {
313                 smb_time_audit_log("rewinddir", timediff);
314         }
315
316 }
317
318 static int smb_time_audit_mkdir(vfs_handle_struct *handle,
319                                 const char *path, mode_t mode)
320 {
321         int result;
322         struct timespec ts1,ts2;
323         double timediff;
324
325         clock_gettime_mono(&ts1);
326         result = SMB_VFS_NEXT_MKDIR(handle, path, mode);
327         clock_gettime_mono(&ts2);
328         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
329
330         if (timediff > audit_timeout) {
331                 smb_time_audit_log("mkdir", timediff);
332         }
333
334         return result;
335 }
336
337 static int smb_time_audit_rmdir(vfs_handle_struct *handle,
338                                 const char *path)
339 {
340         int result;
341         struct timespec ts1,ts2;
342         double timediff;
343
344         clock_gettime_mono(&ts1);
345         result = SMB_VFS_NEXT_RMDIR(handle, path);
346         clock_gettime_mono(&ts2);
347         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
348
349         if (timediff > audit_timeout) {
350                 smb_time_audit_log("rmdir", timediff);
351         }
352
353         return result;
354 }
355
356 static int smb_time_audit_closedir(vfs_handle_struct *handle,
357                                    DIR *dirp)
358 {
359         int result;
360         struct timespec ts1,ts2;
361         double timediff;
362
363         clock_gettime_mono(&ts1);
364         result = SMB_VFS_NEXT_CLOSEDIR(handle, dirp);
365         clock_gettime_mono(&ts2);
366         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
367
368         if (timediff > audit_timeout) {
369                 smb_time_audit_log("closedir", timediff);
370         }
371
372         return result;
373 }
374
375 static void smb_time_audit_init_search_op(vfs_handle_struct *handle,
376                                           DIR *dirp)
377 {
378         struct timespec ts1,ts2;
379         double timediff;
380
381         clock_gettime_mono(&ts1);
382         SMB_VFS_NEXT_INIT_SEARCH_OP(handle, dirp);
383         clock_gettime_mono(&ts2);
384         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
385
386         if (timediff > audit_timeout) {
387                 smb_time_audit_log("init_search_op", timediff);
388         }
389 }
390
391 static int smb_time_audit_open(vfs_handle_struct *handle,
392                                struct smb_filename *fname,
393                                files_struct *fsp,
394                                int flags, mode_t mode)
395 {
396         int result;
397         struct timespec ts1,ts2;
398         double timediff;
399
400         clock_gettime_mono(&ts1);
401         result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
402         clock_gettime_mono(&ts2);
403         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
404
405         if (timediff > audit_timeout) {
406                 smb_time_audit_log("open", timediff);
407         }
408
409         return result;
410 }
411
412 static NTSTATUS smb_time_audit_create_file(vfs_handle_struct *handle,
413                                            struct smb_request *req,
414                                            uint16_t root_dir_fid,
415                                            struct smb_filename *fname,
416                                            uint32_t access_mask,
417                                            uint32_t share_access,
418                                            uint32_t create_disposition,
419                                            uint32_t create_options,
420                                            uint32_t file_attributes,
421                                            uint32_t oplock_request,
422                                            uint64_t allocation_size,
423                                            uint32_t private_flags,
424                                            struct security_descriptor *sd,
425                                            struct ea_list *ea_list,
426                                            files_struct **result_fsp,
427                                            int *pinfo)
428 {
429         NTSTATUS result;
430         struct timespec ts1,ts2;
431         double timediff;
432
433         clock_gettime_mono(&ts1);
434         result = SMB_VFS_NEXT_CREATE_FILE(
435                 handle,                                 /* handle */
436                 req,                                    /* req */
437                 root_dir_fid,                           /* root_dir_fid */
438                 fname,                                  /* fname */
439                 access_mask,                            /* access_mask */
440                 share_access,                           /* share_access */
441                 create_disposition,                     /* create_disposition*/
442                 create_options,                         /* create_options */
443                 file_attributes,                        /* file_attributes */
444                 oplock_request,                         /* oplock_request */
445                 allocation_size,                        /* allocation_size */
446                 private_flags,
447                 sd,                                     /* sd */
448                 ea_list,                                /* ea_list */
449                 result_fsp,                             /* result */
450                 pinfo);
451         clock_gettime_mono(&ts2);
452         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
453
454         if (timediff > audit_timeout) {
455                 smb_time_audit_log("create_file", timediff);
456         }
457
458         return result;
459 }
460
461 static int smb_time_audit_close(vfs_handle_struct *handle, files_struct *fsp)
462 {
463         int result;
464         struct timespec ts1,ts2;
465         double timediff;
466
467         clock_gettime_mono(&ts1);
468         result = SMB_VFS_NEXT_CLOSE(handle, fsp);
469         clock_gettime_mono(&ts2);
470         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
471
472         if (timediff > audit_timeout) {
473                 smb_time_audit_log("close", timediff);
474         }
475
476         return result;
477 }
478
479 static ssize_t smb_time_audit_read(vfs_handle_struct *handle,
480                                    files_struct *fsp, void *data, size_t n)
481 {
482         ssize_t result;
483         struct timespec ts1,ts2;
484         double timediff;
485
486         clock_gettime_mono(&ts1);
487         result = SMB_VFS_NEXT_READ(handle, fsp, data, n);
488         clock_gettime_mono(&ts2);
489         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
490
491         if (timediff > audit_timeout) {
492                 smb_time_audit_log("read", timediff);
493         }
494
495         return result;
496 }
497
498 static ssize_t smb_time_audit_pread(vfs_handle_struct *handle,
499                                     files_struct *fsp,
500                                     void *data, size_t n, off_t offset)
501 {
502         ssize_t result;
503         struct timespec ts1,ts2;
504         double timediff;
505
506         clock_gettime_mono(&ts1);
507         result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
508         clock_gettime_mono(&ts2);
509         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
510
511         if (timediff > audit_timeout) {
512                 smb_time_audit_log("pread", timediff);
513         }
514
515         return result;
516 }
517
518 struct smb_time_audit_pread_state {
519         struct timespec ts1;
520         ssize_t ret;
521         int err;
522 };
523
524 static void smb_time_audit_pread_done(struct tevent_req *subreq);
525
526 static struct tevent_req *smb_time_audit_pread_send(
527         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
528         struct tevent_context *ev, struct files_struct *fsp,
529         void *data, size_t n, off_t offset)
530 {
531         struct tevent_req *req, *subreq;
532         struct smb_time_audit_pread_state *state;
533
534         req = tevent_req_create(mem_ctx, &state,
535                                 struct smb_time_audit_pread_state);
536         if (req == NULL) {
537                 return NULL;
538         }
539         clock_gettime_mono(&state->ts1);
540
541         subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp, data,
542                                          n, offset);
543         if (tevent_req_nomem(subreq, req)) {
544                 return tevent_req_post(req, ev);
545         }
546         tevent_req_set_callback(subreq, smb_time_audit_pread_done, req);
547         return req;
548 }
549
550 static void smb_time_audit_pread_done(struct tevent_req *subreq)
551 {
552         struct tevent_req *req = tevent_req_callback_data(
553                 subreq, struct tevent_req);
554         struct smb_time_audit_pread_state *state = tevent_req_data(
555                 req, struct smb_time_audit_pread_state);
556
557         state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err);
558         TALLOC_FREE(subreq);
559         tevent_req_done(req);
560 }
561
562 static ssize_t smb_time_audit_pread_recv(struct tevent_req *req, int *err)
563 {
564         struct smb_time_audit_pread_state *state = tevent_req_data(
565                 req, struct smb_time_audit_pread_state);
566         struct timespec ts2;
567         double timediff;
568
569         clock_gettime_mono(&ts2);
570         timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
571
572         if (timediff > audit_timeout) {
573                 smb_time_audit_log("pread", timediff);
574         }
575
576         if (tevent_req_is_unix_error(req, err)) {
577                 return -1;
578         }
579         *err = state->err;
580         return state->ret;
581 }
582
583 static ssize_t smb_time_audit_write(vfs_handle_struct *handle,
584                                     files_struct *fsp,
585                                     const void *data, size_t n)
586 {
587         ssize_t result;
588         struct timespec ts1,ts2;
589         double timediff;
590
591         clock_gettime_mono(&ts1);
592         result = SMB_VFS_NEXT_WRITE(handle, fsp, data, n);
593         clock_gettime_mono(&ts2);
594         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
595
596         if (timediff > audit_timeout) {
597                 smb_time_audit_log("write", timediff);
598         }
599
600         return result;
601 }
602
603 static ssize_t smb_time_audit_pwrite(vfs_handle_struct *handle,
604                                      files_struct *fsp,
605                                      const void *data, size_t n,
606                                      off_t offset)
607 {
608         ssize_t result;
609         struct timespec ts1,ts2;
610         double timediff;
611
612         clock_gettime_mono(&ts1);
613         result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
614         clock_gettime_mono(&ts2);
615         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
616
617         if (timediff > audit_timeout) {
618                 smb_time_audit_log("pwrite", timediff);
619         }
620
621         return result;
622 }
623
624 struct smb_time_audit_pwrite_state {
625         struct timespec ts1;
626         ssize_t ret;
627         int err;
628 };
629
630 static void smb_time_audit_pwrite_done(struct tevent_req *subreq);
631
632 static struct tevent_req *smb_time_audit_pwrite_send(
633         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
634         struct tevent_context *ev, struct files_struct *fsp,
635         const void *data, size_t n, off_t offset)
636 {
637         struct tevent_req *req, *subreq;
638         struct smb_time_audit_pwrite_state *state;
639
640         req = tevent_req_create(mem_ctx, &state,
641                                 struct smb_time_audit_pwrite_state);
642         if (req == NULL) {
643                 return NULL;
644         }
645         clock_gettime_mono(&state->ts1);
646
647         subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data,
648                                          n, offset);
649         if (tevent_req_nomem(subreq, req)) {
650                 return tevent_req_post(req, ev);
651         }
652         tevent_req_set_callback(subreq, smb_time_audit_pwrite_done, req);
653         return req;
654 }
655
656 static void smb_time_audit_pwrite_done(struct tevent_req *subreq)
657 {
658         struct tevent_req *req = tevent_req_callback_data(
659                 subreq, struct tevent_req);
660         struct smb_time_audit_pwrite_state *state = tevent_req_data(
661                 req, struct smb_time_audit_pwrite_state);
662
663         state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
664         TALLOC_FREE(subreq);
665         tevent_req_done(req);
666 }
667
668 static ssize_t smb_time_audit_pwrite_recv(struct tevent_req *req, int *err)
669 {
670         struct smb_time_audit_pwrite_state *state = tevent_req_data(
671                 req, struct smb_time_audit_pwrite_state);
672         struct timespec ts2;
673         double timediff;
674
675         clock_gettime_mono(&ts2);
676         timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
677
678         if (timediff > audit_timeout) {
679                 smb_time_audit_log("pwrite", timediff);
680         }
681
682         if (tevent_req_is_unix_error(req, err)) {
683                 return -1;
684         }
685         *err = state->err;
686         return state->ret;
687 }
688
689 static off_t smb_time_audit_lseek(vfs_handle_struct *handle,
690                                       files_struct *fsp,
691                                       off_t offset, int whence)
692 {
693         off_t result;
694         struct timespec ts1,ts2;
695         double timediff;
696
697         clock_gettime_mono(&ts1);
698         result = SMB_VFS_NEXT_LSEEK(handle, fsp, offset, whence);
699         clock_gettime_mono(&ts2);
700         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
701
702         if (timediff > audit_timeout) {
703                 smb_time_audit_log("lseek", timediff);
704         }
705
706         return result;
707 }
708
709 static ssize_t smb_time_audit_sendfile(vfs_handle_struct *handle, int tofd,
710                                        files_struct *fromfsp,
711                                        const DATA_BLOB *hdr, off_t offset,
712                                        size_t n)
713 {
714         ssize_t result;
715         struct timespec ts1,ts2;
716         double timediff;
717
718         clock_gettime_mono(&ts1);
719         result = SMB_VFS_NEXT_SENDFILE(handle, tofd, fromfsp, hdr, offset, n);
720         clock_gettime_mono(&ts2);
721         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
722
723         if (timediff > audit_timeout) {
724                 smb_time_audit_log("sendfile", timediff);
725         }
726
727         return result;
728 }
729
730 static ssize_t smb_time_audit_recvfile(vfs_handle_struct *handle, int fromfd,
731                                        files_struct *tofsp,
732                                        off_t offset,
733                                        size_t n)
734 {
735         ssize_t result;
736         struct timespec ts1,ts2;
737         double timediff;
738
739         clock_gettime_mono(&ts1);
740         result = SMB_VFS_NEXT_RECVFILE(handle, fromfd, tofsp, offset, n);
741         clock_gettime_mono(&ts2);
742         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
743
744         if (timediff > audit_timeout) {
745                 smb_time_audit_log("recvfile", timediff);
746         }
747
748         return result;
749 }
750
751 static int smb_time_audit_rename(vfs_handle_struct *handle,
752                                  const struct smb_filename *oldname,
753                                  const struct smb_filename *newname)
754 {
755         int result;
756         struct timespec ts1,ts2;
757         double timediff;
758
759         clock_gettime_mono(&ts1);
760         result = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
761         clock_gettime_mono(&ts2);
762         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
763
764         if (timediff > audit_timeout) {
765                 smb_time_audit_log("rename", timediff);
766         }
767
768         return result;
769 }
770
771 static int smb_time_audit_fsync(vfs_handle_struct *handle, files_struct *fsp)
772 {
773         int result;
774         struct timespec ts1,ts2;
775         double timediff;
776
777         clock_gettime_mono(&ts1);
778         result = SMB_VFS_NEXT_FSYNC(handle, fsp);
779         clock_gettime_mono(&ts2);
780         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
781
782         if (timediff > audit_timeout) {
783                 smb_time_audit_log("fsync", timediff);
784         }
785
786         return result;
787 }
788
789 struct smb_time_audit_fsync_state {
790         struct timespec ts1;
791         int ret;
792         int err;
793 };
794
795 static void smb_time_audit_fsync_done(struct tevent_req *subreq);
796
797 static struct tevent_req *smb_time_audit_fsync_send(
798         struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
799         struct tevent_context *ev, struct files_struct *fsp)
800 {
801         struct tevent_req *req, *subreq;
802         struct smb_time_audit_fsync_state *state;
803
804         req = tevent_req_create(mem_ctx, &state,
805                                 struct smb_time_audit_fsync_state);
806         if (req == NULL) {
807                 return NULL;
808         }
809         clock_gettime_mono(&state->ts1);
810
811         subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
812         if (tevent_req_nomem(subreq, req)) {
813                 return tevent_req_post(req, ev);
814         }
815         tevent_req_set_callback(subreq, smb_time_audit_fsync_done, req);
816         return req;
817 }
818
819 static void smb_time_audit_fsync_done(struct tevent_req *subreq)
820 {
821         struct tevent_req *req = tevent_req_callback_data(
822                 subreq, struct tevent_req);
823         struct smb_time_audit_fsync_state *state = tevent_req_data(
824                 req, struct smb_time_audit_fsync_state);
825
826         state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->err);
827         TALLOC_FREE(subreq);
828         tevent_req_done(req);
829 }
830
831 static int smb_time_audit_fsync_recv(struct tevent_req *req, int *err)
832 {
833         struct smb_time_audit_fsync_state *state = tevent_req_data(
834                 req, struct smb_time_audit_fsync_state);
835         struct timespec ts2;
836         double timediff;
837
838         clock_gettime_mono(&ts2);
839         timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
840
841         if (timediff > audit_timeout) {
842                 smb_time_audit_log("fsync", timediff);
843         }
844
845         if (tevent_req_is_unix_error(req, err)) {
846                 return -1;
847         }
848         *err = state->err;
849         return state->ret;
850 }
851
852 static int smb_time_audit_stat(vfs_handle_struct *handle,
853                                struct smb_filename *fname)
854 {
855         int result;
856         struct timespec ts1,ts2;
857         double timediff;
858
859         clock_gettime_mono(&ts1);
860         result = SMB_VFS_NEXT_STAT(handle, fname);
861         clock_gettime_mono(&ts2);
862         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
863
864         if (timediff > audit_timeout) {
865                 smb_time_audit_log("stat", timediff);
866         }
867
868         return result;
869 }
870
871 static int smb_time_audit_fstat(vfs_handle_struct *handle, files_struct *fsp,
872                                 SMB_STRUCT_STAT *sbuf)
873 {
874         int result;
875         struct timespec ts1,ts2;
876         double timediff;
877
878         clock_gettime_mono(&ts1);
879         result = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
880         clock_gettime_mono(&ts2);
881         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
882
883         if (timediff > audit_timeout) {
884                 smb_time_audit_log("fstat", timediff);
885         }
886
887         return result;
888 }
889
890 static int smb_time_audit_lstat(vfs_handle_struct *handle,
891                                 struct smb_filename *path)
892 {
893         int result;
894         struct timespec ts1,ts2;
895         double timediff;
896
897         clock_gettime_mono(&ts1);
898         result = SMB_VFS_NEXT_LSTAT(handle, path);
899         clock_gettime_mono(&ts2);
900         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
901
902         if (timediff > audit_timeout) {
903                 smb_time_audit_log("lstat", timediff);
904         }
905
906         return result;
907 }
908
909 static uint64_t smb_time_audit_get_alloc_size(vfs_handle_struct *handle,
910                                               files_struct *fsp,
911                                               const SMB_STRUCT_STAT *sbuf)
912 {
913         uint64_t result;
914         struct timespec ts1,ts2;
915         double timediff;
916
917         clock_gettime_mono(&ts1);
918         result = SMB_VFS_NEXT_GET_ALLOC_SIZE(handle, fsp, sbuf);
919         clock_gettime_mono(&ts2);
920         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
921
922         if (timediff > audit_timeout) {
923                 smb_time_audit_log("get_alloc_size", timediff);
924         }
925
926         return result;
927 }
928
929 static int smb_time_audit_unlink(vfs_handle_struct *handle,
930                                  const struct smb_filename *path)
931 {
932         int result;
933         struct timespec ts1,ts2;
934         double timediff;
935
936         clock_gettime_mono(&ts1);
937         result = SMB_VFS_NEXT_UNLINK(handle, path);
938         clock_gettime_mono(&ts2);
939         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
940
941         if (timediff > audit_timeout) {
942                 smb_time_audit_log("unlink", timediff);
943         }
944
945         return result;
946 }
947
948 static int smb_time_audit_chmod(vfs_handle_struct *handle,
949                                 const char *path, mode_t mode)
950 {
951         int result;
952         struct timespec ts1,ts2;
953         double timediff;
954
955         clock_gettime_mono(&ts1);
956         result = SMB_VFS_NEXT_CHMOD(handle, path, mode);
957         clock_gettime_mono(&ts2);
958         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
959
960         if (timediff > audit_timeout) {
961                 smb_time_audit_log("chmod", timediff);
962         }
963
964         return result;
965 }
966
967 static int smb_time_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp,
968                                  mode_t mode)
969 {
970         int result;
971         struct timespec ts1,ts2;
972         double timediff;
973
974         clock_gettime_mono(&ts1);
975         result = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
976         clock_gettime_mono(&ts2);
977         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
978
979         if (timediff > audit_timeout) {
980                 smb_time_audit_log("fchmod", timediff);
981         }
982
983         return result;
984 }
985
986 static int smb_time_audit_chown(vfs_handle_struct *handle,
987                                 const char *path, uid_t uid, gid_t gid)
988 {
989         int result;
990         struct timespec ts1,ts2;
991         double timediff;
992
993         clock_gettime_mono(&ts1);
994         result = SMB_VFS_NEXT_CHOWN(handle, path, uid, gid);
995         clock_gettime_mono(&ts2);
996         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
997
998         if (timediff > audit_timeout) {
999                 smb_time_audit_log("chown", timediff);
1000         }
1001
1002         return result;
1003 }
1004
1005 static int smb_time_audit_fchown(vfs_handle_struct *handle, files_struct *fsp,
1006                                  uid_t uid, gid_t gid)
1007 {
1008         int result;
1009         struct timespec ts1,ts2;
1010         double timediff;
1011
1012         clock_gettime_mono(&ts1);
1013         result = SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid);
1014         clock_gettime_mono(&ts2);
1015         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1016
1017         if (timediff > audit_timeout) {
1018                 smb_time_audit_log("fchown", timediff);
1019         }
1020
1021         return result;
1022 }
1023
1024 static int smb_time_audit_lchown(vfs_handle_struct *handle,
1025                                  const char *path, uid_t uid, gid_t gid)
1026 {
1027         int result;
1028         struct timespec ts1,ts2;
1029         double timediff;
1030
1031         clock_gettime_mono(&ts1);
1032         result = SMB_VFS_NEXT_LCHOWN(handle, path, uid, gid);
1033         clock_gettime_mono(&ts2);
1034         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1035
1036         if (timediff > audit_timeout) {
1037                 smb_time_audit_log("lchown", timediff);
1038         }
1039
1040         return result;
1041 }
1042
1043 static int smb_time_audit_chdir(vfs_handle_struct *handle, const char *path)
1044 {
1045         int result;
1046         struct timespec ts1,ts2;
1047         double timediff;
1048
1049         clock_gettime_mono(&ts1);
1050         result = SMB_VFS_NEXT_CHDIR(handle, path);
1051         clock_gettime_mono(&ts2);
1052         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1053
1054         if (timediff > audit_timeout) {
1055                 smb_time_audit_log("chdir", timediff);
1056         }
1057
1058         return result;
1059 }
1060
1061 static char *smb_time_audit_getwd(vfs_handle_struct *handle)
1062 {
1063         char *result;
1064         struct timespec ts1,ts2;
1065         double timediff;
1066
1067         clock_gettime_mono(&ts1);
1068         result = SMB_VFS_NEXT_GETWD(handle);
1069         clock_gettime_mono(&ts2);
1070         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1071
1072         if (timediff > audit_timeout) {
1073                 smb_time_audit_log("getwd", timediff);
1074         }
1075
1076         return result;
1077 }
1078
1079 static int smb_time_audit_ntimes(vfs_handle_struct *handle,
1080                                  const struct smb_filename *path,
1081                                  struct smb_file_time *ft)
1082 {
1083         int result;
1084         struct timespec ts1,ts2;
1085         double timediff;
1086
1087         clock_gettime_mono(&ts1);
1088         result = SMB_VFS_NEXT_NTIMES(handle, path, ft);
1089         clock_gettime_mono(&ts2);
1090         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1091
1092         if (timediff > audit_timeout) {
1093                 smb_time_audit_log("ntimes", timediff);
1094         }
1095
1096         return result;
1097 }
1098
1099 static int smb_time_audit_ftruncate(vfs_handle_struct *handle,
1100                                     files_struct *fsp,
1101                                     off_t len)
1102 {
1103         int result;
1104         struct timespec ts1,ts2;
1105         double timediff;
1106
1107         clock_gettime_mono(&ts1);
1108         result = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len);
1109         clock_gettime_mono(&ts2);
1110         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1111
1112         if (timediff > audit_timeout) {
1113                 smb_time_audit_log("ftruncate", timediff);
1114         }
1115
1116         return result;
1117 }
1118
1119 static int smb_time_audit_fallocate(vfs_handle_struct *handle,
1120                                     files_struct *fsp,
1121                                     enum vfs_fallocate_mode mode,
1122                                     off_t offset,
1123                                     off_t len)
1124 {
1125         int result;
1126         struct timespec ts1,ts2;
1127         double timediff;
1128
1129         clock_gettime_mono(&ts1);
1130         result = SMB_VFS_NEXT_FALLOCATE(handle, fsp, mode, offset, len);
1131         clock_gettime_mono(&ts2);
1132         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1133
1134         if (timediff > audit_timeout) {
1135                 smb_time_audit_log("fallocate", timediff);
1136         }
1137
1138         return result;
1139 }
1140
1141 static bool smb_time_audit_lock(vfs_handle_struct *handle, files_struct *fsp,
1142                                 int op, off_t offset, off_t count,
1143                                 int type)
1144 {
1145         bool result;
1146         struct timespec ts1,ts2;
1147         double timediff;
1148
1149         clock_gettime_mono(&ts1);
1150         result = SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type);
1151         clock_gettime_mono(&ts2);
1152         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1153
1154         if (timediff > audit_timeout) {
1155                 smb_time_audit_log("lock", timediff);
1156         }
1157
1158         return result;
1159 }
1160
1161 static int smb_time_audit_kernel_flock(struct vfs_handle_struct *handle,
1162                                        struct files_struct *fsp,
1163                                        uint32 share_mode, uint32 access_mask)
1164 {
1165         int result;
1166         struct timespec ts1,ts2;
1167         double timediff;
1168
1169         clock_gettime_mono(&ts1);
1170         result = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode,
1171                                            access_mask);
1172         clock_gettime_mono(&ts2);
1173         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1174
1175         if (timediff > audit_timeout) {
1176                 smb_time_audit_log("kernel_flock", timediff);
1177         }
1178
1179         return result;
1180 }
1181
1182 static int smb_time_audit_linux_setlease(vfs_handle_struct *handle,
1183                                          files_struct *fsp,
1184                                          int leasetype)
1185 {
1186         int result;
1187         struct timespec ts1,ts2;
1188         double timediff;
1189
1190         clock_gettime_mono(&ts1);
1191         result = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype);
1192         clock_gettime_mono(&ts2);
1193         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1194
1195         if (timediff > audit_timeout) {
1196                 smb_time_audit_log("linux_setlease", timediff);
1197         }
1198
1199         return result;
1200 }
1201
1202 static bool smb_time_audit_getlock(vfs_handle_struct *handle,
1203                                    files_struct *fsp,
1204                                    off_t *poffset, off_t *pcount,
1205                                    int *ptype, pid_t *ppid)
1206 {
1207         bool result;
1208         struct timespec ts1,ts2;
1209         double timediff;
1210
1211         clock_gettime_mono(&ts1);
1212         result = SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype,
1213                                       ppid);
1214         clock_gettime_mono(&ts2);
1215         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1216
1217         if (timediff > audit_timeout) {
1218                 smb_time_audit_log("getlock", timediff);
1219         }
1220
1221         return result;
1222 }
1223
1224 static int smb_time_audit_symlink(vfs_handle_struct *handle,
1225                                   const char *oldpath, const char *newpath)
1226 {
1227         int result;
1228         struct timespec ts1,ts2;
1229         double timediff;
1230
1231         clock_gettime_mono(&ts1);
1232         result = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
1233         clock_gettime_mono(&ts2);
1234         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1235
1236         if (timediff > audit_timeout) {
1237                 smb_time_audit_log("symlink", timediff);
1238         }
1239
1240         return result;
1241 }
1242
1243 static int smb_time_audit_readlink(vfs_handle_struct *handle,
1244                           const char *path, char *buf, size_t bufsiz)
1245 {
1246         int result;
1247         struct timespec ts1,ts2;
1248         double timediff;
1249
1250         clock_gettime_mono(&ts1);
1251         result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz);
1252         clock_gettime_mono(&ts2);
1253         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1254
1255         if (timediff > audit_timeout) {
1256                 smb_time_audit_log("readlink", timediff);
1257         }
1258
1259         return result;
1260 }
1261
1262 static int smb_time_audit_link(vfs_handle_struct *handle,
1263                                const char *oldpath, const char *newpath)
1264 {
1265         int result;
1266         struct timespec ts1,ts2;
1267         double timediff;
1268
1269         clock_gettime_mono(&ts1);
1270         result = SMB_VFS_NEXT_LINK(handle, oldpath, newpath);
1271         clock_gettime_mono(&ts2);
1272         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1273
1274         if (timediff > audit_timeout) {
1275                 smb_time_audit_log("link", timediff);
1276         }
1277
1278         return result;
1279 }
1280
1281 static int smb_time_audit_mknod(vfs_handle_struct *handle,
1282                                 const char *pathname, mode_t mode,
1283                                 SMB_DEV_T dev)
1284 {
1285         int result;
1286         struct timespec ts1,ts2;
1287         double timediff;
1288
1289         clock_gettime_mono(&ts1);
1290         result = SMB_VFS_NEXT_MKNOD(handle, pathname, mode, dev);
1291         clock_gettime_mono(&ts2);
1292         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1293
1294         if (timediff > audit_timeout) {
1295                 smb_time_audit_log("mknod", timediff);
1296         }
1297
1298         return result;
1299 }
1300
1301 static char *smb_time_audit_realpath(vfs_handle_struct *handle,
1302                                      const char *path)
1303 {
1304         char *result;
1305         struct timespec ts1,ts2;
1306         double timediff;
1307
1308         clock_gettime_mono(&ts1);
1309         result = SMB_VFS_NEXT_REALPATH(handle, path);
1310         clock_gettime_mono(&ts2);
1311         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1312
1313         if (timediff > audit_timeout) {
1314                 smb_time_audit_log("realpath", timediff);
1315         }
1316
1317         return result;
1318 }
1319
1320 static NTSTATUS smb_time_audit_notify_watch(struct vfs_handle_struct *handle,
1321                         struct sys_notify_context *ctx,
1322                         const char *path,
1323                         uint32_t *filter,
1324                         uint32_t *subdir_filter,
1325                         void (*callback)(struct sys_notify_context *ctx,
1326                                         void *private_data,
1327                                         struct notify_event *ev),
1328                         void *private_data, void *handle_p)
1329 {
1330         NTSTATUS result;
1331         struct timespec ts1,ts2;
1332         double timediff;
1333
1334         clock_gettime_mono(&ts1);
1335         result = SMB_VFS_NEXT_NOTIFY_WATCH(handle, ctx, path,
1336                                            filter, subdir_filter, callback,
1337                                            private_data, handle_p);
1338         clock_gettime_mono(&ts2);
1339         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1340
1341         if (timediff > audit_timeout) {
1342                 smb_time_audit_log("notify_watch", timediff);
1343         }
1344
1345         return result;
1346 }
1347
1348 static int smb_time_audit_chflags(vfs_handle_struct *handle,
1349                                   const char *path, unsigned int flags)
1350 {
1351         int result;
1352         struct timespec ts1,ts2;
1353         double timediff;
1354
1355         clock_gettime_mono(&ts1);
1356         result = SMB_VFS_NEXT_CHFLAGS(handle, path, flags);
1357         clock_gettime_mono(&ts2);
1358         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1359
1360         if (timediff > audit_timeout) {
1361                 smb_time_audit_log("chflags", timediff);
1362         }
1363
1364         return result;
1365 }
1366
1367 static struct file_id smb_time_audit_file_id_create(struct vfs_handle_struct *handle,
1368                                                     const SMB_STRUCT_STAT *sbuf)
1369 {
1370         struct file_id id_zero;
1371         struct file_id result;
1372         struct timespec ts1,ts2;
1373         double timediff;
1374
1375         ZERO_STRUCT(id_zero);
1376
1377         clock_gettime_mono(&ts1);
1378         result = SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
1379         clock_gettime_mono(&ts2);
1380         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1381
1382         if (timediff > audit_timeout) {
1383                 smb_time_audit_log("file_id_create", timediff);
1384         }
1385
1386         return result;
1387 }
1388
1389 static NTSTATUS smb_time_audit_streaminfo(vfs_handle_struct *handle,
1390                                           struct files_struct *fsp,
1391                                           const char *fname,
1392                                           TALLOC_CTX *mem_ctx,
1393                                           unsigned int *pnum_streams,
1394                                           struct stream_struct **pstreams)
1395 {
1396         NTSTATUS result;
1397         struct timespec ts1,ts2;
1398         double timediff;
1399
1400         clock_gettime_mono(&ts1);
1401         result = SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx,
1402                                          pnum_streams, pstreams);
1403         clock_gettime_mono(&ts2);
1404         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1405
1406         if (timediff > audit_timeout) {
1407                 smb_time_audit_log("streaminfo", timediff);
1408         }
1409
1410         return result;
1411 }
1412
1413 static int smb_time_audit_get_real_filename(struct vfs_handle_struct *handle,
1414                                             const char *path,
1415                                             const char *name,
1416                                             TALLOC_CTX *mem_ctx,
1417                                             char **found_name)
1418 {
1419         int result;
1420         struct timespec ts1,ts2;
1421         double timediff;
1422
1423         clock_gettime_mono(&ts1);
1424         result = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx,
1425                                                 found_name);
1426         clock_gettime_mono(&ts2);
1427         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1428
1429         if (timediff > audit_timeout) {
1430                 smb_time_audit_log("get_real_filename", timediff);
1431         }
1432
1433         return result;
1434 }
1435
1436 static const char *smb_time_audit_connectpath(vfs_handle_struct *handle,
1437                                               const char *fname)
1438 {
1439         const char *result;
1440         struct timespec ts1,ts2;
1441         double timediff;
1442
1443         clock_gettime_mono(&ts1);
1444         result = SMB_VFS_NEXT_CONNECTPATH(handle, fname);
1445         clock_gettime_mono(&ts2);
1446         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1447
1448         if (timediff > audit_timeout) {
1449                 smb_time_audit_log("connectpath", timediff);
1450         }
1451
1452         return result;
1453 }
1454
1455 static NTSTATUS smb_time_audit_brl_lock_windows(struct vfs_handle_struct *handle,
1456                                                 struct byte_range_lock *br_lck,
1457                                                 struct lock_struct *plock,
1458                                                 bool blocking_lock,
1459                                                 struct blocking_lock_record *blr)
1460 {
1461         NTSTATUS result;
1462         struct timespec ts1,ts2;
1463         double timediff;
1464
1465         clock_gettime_mono(&ts1);
1466         result = SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock,
1467                                                blocking_lock, blr);
1468         clock_gettime_mono(&ts2);
1469         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1470
1471         if (timediff > audit_timeout) {
1472                 smb_time_audit_log("brl_lock_windows", timediff);
1473         }
1474
1475         return result;
1476 }
1477
1478 static bool smb_time_audit_brl_unlock_windows(struct vfs_handle_struct *handle,
1479                                               struct messaging_context *msg_ctx,
1480                                               struct byte_range_lock *br_lck,
1481                                               const struct lock_struct *plock)
1482 {
1483         bool result;
1484         struct timespec ts1,ts2;
1485         double timediff;
1486
1487         clock_gettime_mono(&ts1);
1488         result = SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, msg_ctx, br_lck,
1489                                                  plock);
1490         clock_gettime_mono(&ts2);
1491         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1492
1493         if (timediff > audit_timeout) {
1494                 smb_time_audit_log("brl_unlock_windows", timediff);
1495         }
1496
1497         return result;
1498 }
1499
1500 static bool smb_time_audit_brl_cancel_windows(struct vfs_handle_struct *handle,
1501                                               struct byte_range_lock *br_lck,
1502                                               struct lock_struct *plock,
1503                                               struct blocking_lock_record *blr)
1504 {
1505         bool result;
1506         struct timespec ts1,ts2;
1507         double timediff;
1508
1509         clock_gettime_mono(&ts1);
1510         result = SMB_VFS_NEXT_BRL_CANCEL_WINDOWS(handle, br_lck, plock, blr);
1511         clock_gettime_mono(&ts2);
1512         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1513
1514         if (timediff > audit_timeout) {
1515                 smb_time_audit_log("brl_cancel_windows", timediff);
1516         }
1517
1518         return result;
1519 }
1520
1521 static bool smb_time_audit_strict_lock(struct vfs_handle_struct *handle,
1522                                        struct files_struct *fsp,
1523                                        struct lock_struct *plock)
1524 {
1525         bool result;
1526         struct timespec ts1,ts2;
1527         double timediff;
1528
1529         clock_gettime_mono(&ts1);
1530         result = SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock);
1531         clock_gettime_mono(&ts2);
1532         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1533
1534         if (timediff > audit_timeout) {
1535                 smb_time_audit_log("strict_lock", timediff);
1536         }
1537
1538         return result;
1539 }
1540
1541 static void smb_time_audit_strict_unlock(struct vfs_handle_struct *handle,
1542                                          struct files_struct *fsp,
1543                                          struct lock_struct *plock)
1544 {
1545         struct timespec ts1,ts2;
1546         double timediff;
1547
1548         clock_gettime_mono(&ts1);
1549         SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock);
1550         clock_gettime_mono(&ts2);
1551         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1552
1553         if (timediff > audit_timeout) {
1554                 smb_time_audit_log("strict_unlock", timediff);
1555         }
1556 }
1557
1558 static NTSTATUS smb_time_audit_translate_name(struct vfs_handle_struct *handle,
1559                                               const char *name,
1560                                               enum vfs_translate_direction direction,
1561                                               TALLOC_CTX *mem_ctx,
1562                                               char **mapped_name)
1563 {
1564         NTSTATUS result;
1565         struct timespec ts1,ts2;
1566         double timediff;
1567
1568         clock_gettime_mono(&ts1);
1569         result = SMB_VFS_NEXT_TRANSLATE_NAME(handle, name, direction, mem_ctx,
1570                                              mapped_name);
1571         clock_gettime_mono(&ts2);
1572         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1573
1574         if (timediff > audit_timeout) {
1575                 smb_time_audit_log("translate_name", timediff);
1576         }
1577
1578         return result;
1579 }
1580
1581 static NTSTATUS smb_time_audit_fget_nt_acl(vfs_handle_struct *handle,
1582                                            files_struct *fsp,
1583                                            uint32 security_info,
1584                                            struct security_descriptor **ppdesc)
1585 {
1586         NTSTATUS result;
1587         struct timespec ts1,ts2;
1588         double timediff;
1589
1590         clock_gettime_mono(&ts1);
1591         result = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc);
1592         clock_gettime_mono(&ts2);
1593         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1594
1595         if (timediff > audit_timeout) {
1596                 smb_time_audit_log("fget_nt_acl", timediff);
1597         }
1598
1599         return result;
1600 }
1601
1602 static NTSTATUS smb_time_audit_get_nt_acl(vfs_handle_struct *handle,
1603                                           const char *name,
1604                                           uint32 security_info,
1605                                           struct security_descriptor **ppdesc)
1606 {
1607         NTSTATUS result;
1608         struct timespec ts1,ts2;
1609         double timediff;
1610
1611         clock_gettime_mono(&ts1);
1612         result = SMB_VFS_NEXT_GET_NT_ACL(handle, name, security_info, ppdesc);
1613         clock_gettime_mono(&ts2);
1614         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1615
1616         if (timediff > audit_timeout) {
1617                 smb_time_audit_log("get_nt_acl", timediff);
1618         }
1619
1620         return result;
1621 }
1622
1623 static NTSTATUS smb_time_audit_fset_nt_acl(vfs_handle_struct *handle,
1624                                            files_struct *fsp,
1625                                            uint32 security_info_sent,
1626                                            const struct security_descriptor *psd)
1627 {
1628         NTSTATUS result;
1629         struct timespec ts1,ts2;
1630         double timediff;
1631
1632         clock_gettime_mono(&ts1);
1633         result = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent,
1634                                           psd);
1635         clock_gettime_mono(&ts2);
1636         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1637
1638         if (timediff > audit_timeout) {
1639                 smb_time_audit_log("fset_nt_acl", timediff);
1640         }
1641
1642         return result;
1643 }
1644
1645 static int smb_time_audit_chmod_acl(vfs_handle_struct *handle,
1646                                     const char *path, mode_t mode)
1647 {
1648         int result;
1649         struct timespec ts1,ts2;
1650         double timediff;
1651
1652         clock_gettime_mono(&ts1);
1653         result = SMB_VFS_NEXT_CHMOD_ACL(handle, path, mode);
1654         clock_gettime_mono(&ts2);
1655         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1656
1657         if (timediff > audit_timeout) {
1658                 smb_time_audit_log("chmod_acl", timediff);
1659         }
1660
1661         return result;
1662 }
1663
1664 static int smb_time_audit_fchmod_acl(vfs_handle_struct *handle,
1665                                      files_struct *fsp, mode_t mode)
1666 {
1667         int result;
1668         struct timespec ts1,ts2;
1669         double timediff;
1670
1671         clock_gettime_mono(&ts1);
1672         result = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
1673         clock_gettime_mono(&ts2);
1674         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1675
1676         if (timediff > audit_timeout) {
1677                 smb_time_audit_log("fchmod_acl", timediff);
1678         }
1679
1680         return result;
1681 }
1682
1683 static SMB_ACL_T smb_time_audit_sys_acl_get_file(vfs_handle_struct *handle,
1684                                                  const char *path_p,
1685                                                  SMB_ACL_TYPE_T type)
1686 {
1687         SMB_ACL_T result;
1688         struct timespec ts1,ts2;
1689         double timediff;
1690
1691         clock_gettime_mono(&ts1);
1692         result = SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p, type);
1693         clock_gettime_mono(&ts2);
1694         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1695
1696         if (timediff > audit_timeout) {
1697                 smb_time_audit_log("sys_acl_get_file", timediff);
1698         }
1699
1700         return result;
1701 }
1702
1703 static SMB_ACL_T smb_time_audit_sys_acl_get_fd(vfs_handle_struct *handle,
1704                                                files_struct *fsp)
1705 {
1706         SMB_ACL_T result;
1707         struct timespec ts1,ts2;
1708         double timediff;
1709
1710         clock_gettime_mono(&ts1);
1711         result = SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp);
1712         clock_gettime_mono(&ts2);
1713         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1714
1715         if (timediff > audit_timeout) {
1716                 smb_time_audit_log("sys_acl_get_fd", timediff);
1717         }
1718
1719         return result;
1720 }
1721
1722 static int smb_time_audit_sys_acl_set_file(vfs_handle_struct *handle,
1723                                            const char *name,
1724                                            SMB_ACL_TYPE_T acltype,
1725                                            SMB_ACL_T theacl)
1726 {
1727         int result;
1728         struct timespec ts1,ts2;
1729         double timediff;
1730
1731         clock_gettime_mono(&ts1);
1732         result = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, acltype,
1733                                                theacl);
1734         clock_gettime_mono(&ts2);
1735         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1736
1737         if (timediff > audit_timeout) {
1738                 smb_time_audit_log("sys_acl_set_file", timediff);
1739         }
1740
1741         return result;
1742 }
1743
1744 static int smb_time_audit_sys_acl_set_fd(vfs_handle_struct *handle,
1745                                          files_struct *fsp,
1746                                          SMB_ACL_T theacl)
1747 {
1748         int result;
1749         struct timespec ts1,ts2;
1750         double timediff;
1751
1752         clock_gettime_mono(&ts1);
1753         result = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
1754         clock_gettime_mono(&ts2);
1755         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1756
1757         if (timediff > audit_timeout) {
1758                 smb_time_audit_log("sys_acl_set_fd", timediff);
1759         }
1760
1761         return result;
1762 }
1763
1764 static int smb_time_audit_sys_acl_delete_def_file(vfs_handle_struct *handle,
1765                                                   const char *path)
1766 {
1767         int result;
1768         struct timespec ts1,ts2;
1769         double timediff;
1770
1771         clock_gettime_mono(&ts1);
1772         result = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path);
1773         clock_gettime_mono(&ts2);
1774         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1775
1776         if (timediff > audit_timeout) {
1777                 smb_time_audit_log("sys_acl_delete_def_file", timediff);
1778         }
1779
1780         return result;
1781 }
1782
1783 static ssize_t smb_time_audit_getxattr(struct vfs_handle_struct *handle,
1784                                        const char *path, const char *name,
1785                                        void *value, size_t size)
1786 {
1787         ssize_t result;
1788         struct timespec ts1,ts2;
1789         double timediff;
1790
1791         clock_gettime_mono(&ts1);
1792         result = SMB_VFS_NEXT_GETXATTR(handle, path, name, value, size);
1793         clock_gettime_mono(&ts2);
1794         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1795
1796         if (timediff > audit_timeout) {
1797                 smb_time_audit_log("getxattr", timediff);
1798         }
1799
1800         return result;
1801 }
1802
1803 static ssize_t smb_time_audit_fgetxattr(struct vfs_handle_struct *handle,
1804                                         struct files_struct *fsp,
1805                                         const char *name, void *value,
1806                                         size_t size)
1807 {
1808         ssize_t result;
1809         struct timespec ts1,ts2;
1810         double timediff;
1811
1812         clock_gettime_mono(&ts1);
1813         result = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size);
1814         clock_gettime_mono(&ts2);
1815         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1816
1817         if (timediff > audit_timeout) {
1818                 smb_time_audit_log("fgetxattr", timediff);
1819         }
1820
1821         return result;
1822 }
1823
1824 static ssize_t smb_time_audit_listxattr(struct vfs_handle_struct *handle,
1825                                         const char *path, char *list,
1826                                         size_t size)
1827 {
1828         ssize_t result;
1829         struct timespec ts1,ts2;
1830         double timediff;
1831
1832         clock_gettime_mono(&ts1);
1833         result = SMB_VFS_NEXT_LISTXATTR(handle, path, list, size);
1834         clock_gettime_mono(&ts2);
1835         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1836
1837         if (timediff > audit_timeout) {
1838                 smb_time_audit_log("listxattr", timediff);
1839         }
1840
1841         return result;
1842 }
1843
1844 static ssize_t smb_time_audit_flistxattr(struct vfs_handle_struct *handle,
1845                                          struct files_struct *fsp, char *list,
1846                                          size_t size)
1847 {
1848         ssize_t result;
1849         struct timespec ts1,ts2;
1850         double timediff;
1851
1852         clock_gettime_mono(&ts1);
1853         result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size);
1854         clock_gettime_mono(&ts2);
1855         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1856
1857         if (timediff > audit_timeout) {
1858                 smb_time_audit_log("flistxattr", timediff);
1859         }
1860
1861         return result;
1862 }
1863
1864 static int smb_time_audit_removexattr(struct vfs_handle_struct *handle,
1865                                       const char *path, const char *name)
1866 {
1867         int result;
1868         struct timespec ts1,ts2;
1869         double timediff;
1870
1871         clock_gettime_mono(&ts1);
1872         result = SMB_VFS_NEXT_REMOVEXATTR(handle, path, name);
1873         clock_gettime_mono(&ts2);
1874         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1875
1876         if (timediff > audit_timeout) {
1877                 smb_time_audit_log("removexattr", timediff);
1878         }
1879
1880         return result;
1881 }
1882
1883 static int smb_time_audit_fremovexattr(struct vfs_handle_struct *handle,
1884                                        struct files_struct *fsp,
1885                                        const char *name)
1886 {
1887         int result;
1888         struct timespec ts1,ts2;
1889         double timediff;
1890
1891         clock_gettime_mono(&ts1);
1892         result = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name);
1893         clock_gettime_mono(&ts2);
1894         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1895
1896         if (timediff > audit_timeout) {
1897                 smb_time_audit_log("fremovexattr", timediff);
1898         }
1899
1900         return result;
1901 }
1902
1903 static int smb_time_audit_setxattr(struct vfs_handle_struct *handle,
1904                                    const char *path, const char *name,
1905                                    const void *value, size_t size,
1906                                    int flags)
1907 {
1908         int result;
1909         struct timespec ts1,ts2;
1910         double timediff;
1911
1912         clock_gettime_mono(&ts1);
1913         result = SMB_VFS_NEXT_SETXATTR(handle, path, name, value, size,
1914                                        flags);
1915         clock_gettime_mono(&ts2);
1916         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1917
1918         if (timediff > audit_timeout) {
1919                 smb_time_audit_log("setxattr", timediff);
1920         }
1921
1922         return result;
1923 }
1924
1925 static int smb_time_audit_fsetxattr(struct vfs_handle_struct *handle,
1926                                     struct files_struct *fsp, const char *name,
1927                                     const void *value, size_t size, int flags)
1928 {
1929         int result;
1930         struct timespec ts1,ts2;
1931         double timediff;
1932
1933         clock_gettime_mono(&ts1);
1934         result = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, value, size, flags);
1935         clock_gettime_mono(&ts2);
1936         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1937
1938         if (timediff > audit_timeout) {
1939                 smb_time_audit_log("fsetxattr", timediff);
1940         }
1941
1942         return result;
1943 }
1944
1945 static bool smb_time_audit_aio_force(struct vfs_handle_struct *handle,
1946                                      struct files_struct *fsp)
1947 {
1948         bool result;
1949         struct timespec ts1,ts2;
1950         double timediff;
1951
1952         clock_gettime_mono(&ts1);
1953         result = SMB_VFS_NEXT_AIO_FORCE(handle, fsp);
1954         clock_gettime_mono(&ts2);
1955         timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
1956
1957         if (timediff > audit_timeout) {
1958                 smb_time_audit_log("aio_force", timediff);
1959         }
1960
1961         return result;
1962 }
1963
1964
1965
1966 /* VFS operations */
1967
1968 static struct vfs_fn_pointers vfs_time_audit_fns = {
1969         .connect_fn = smb_time_audit_connect,
1970         .disconnect_fn = smb_time_audit_disconnect,
1971         .disk_free_fn = smb_time_audit_disk_free,
1972         .get_quota_fn = smb_time_audit_get_quota,
1973         .set_quota_fn = smb_time_audit_set_quota,
1974         .get_shadow_copy_data_fn = smb_time_audit_get_shadow_copy_data,
1975         .statvfs_fn = smb_time_audit_statvfs,
1976         .fs_capabilities_fn = smb_time_audit_fs_capabilities,
1977         .opendir_fn = smb_time_audit_opendir,
1978         .fdopendir_fn = smb_time_audit_fdopendir,
1979         .readdir_fn = smb_time_audit_readdir,
1980         .seekdir_fn = smb_time_audit_seekdir,
1981         .telldir_fn = smb_time_audit_telldir,
1982         .rewind_dir_fn = smb_time_audit_rewinddir,
1983         .mkdir_fn = smb_time_audit_mkdir,
1984         .rmdir_fn = smb_time_audit_rmdir,
1985         .closedir_fn = smb_time_audit_closedir,
1986         .init_search_op_fn = smb_time_audit_init_search_op,
1987         .open_fn = smb_time_audit_open,
1988         .create_file_fn = smb_time_audit_create_file,
1989         .close_fn = smb_time_audit_close,
1990         .read_fn = smb_time_audit_read,
1991         .pread_fn = smb_time_audit_pread,
1992         .pread_send_fn = smb_time_audit_pread_send,
1993         .pread_recv_fn = smb_time_audit_pread_recv,
1994         .write_fn = smb_time_audit_write,
1995         .pwrite_fn = smb_time_audit_pwrite,
1996         .pwrite_send_fn = smb_time_audit_pwrite_send,
1997         .pwrite_recv_fn = smb_time_audit_pwrite_recv,
1998         .lseek_fn = smb_time_audit_lseek,
1999         .sendfile_fn = smb_time_audit_sendfile,
2000         .recvfile_fn = smb_time_audit_recvfile,
2001         .rename_fn = smb_time_audit_rename,
2002         .fsync_fn = smb_time_audit_fsync,
2003         .fsync_send_fn = smb_time_audit_fsync_send,
2004         .fsync_recv_fn = smb_time_audit_fsync_recv,
2005         .stat_fn = smb_time_audit_stat,
2006         .fstat_fn = smb_time_audit_fstat,
2007         .lstat_fn = smb_time_audit_lstat,
2008         .get_alloc_size_fn = smb_time_audit_get_alloc_size,
2009         .unlink_fn = smb_time_audit_unlink,
2010         .chmod_fn = smb_time_audit_chmod,
2011         .fchmod_fn = smb_time_audit_fchmod,
2012         .chown_fn = smb_time_audit_chown,
2013         .fchown_fn = smb_time_audit_fchown,
2014         .lchown_fn = smb_time_audit_lchown,
2015         .chdir_fn = smb_time_audit_chdir,
2016         .getwd_fn = smb_time_audit_getwd,
2017         .ntimes_fn = smb_time_audit_ntimes,
2018         .ftruncate_fn = smb_time_audit_ftruncate,
2019         .fallocate_fn = smb_time_audit_fallocate,
2020         .lock_fn = smb_time_audit_lock,
2021         .kernel_flock_fn = smb_time_audit_kernel_flock,
2022         .linux_setlease_fn = smb_time_audit_linux_setlease,
2023         .getlock_fn = smb_time_audit_getlock,
2024         .symlink_fn = smb_time_audit_symlink,
2025         .readlink_fn = smb_time_audit_readlink,
2026         .link_fn = smb_time_audit_link,
2027         .mknod_fn = smb_time_audit_mknod,
2028         .realpath_fn = smb_time_audit_realpath,
2029         .notify_watch_fn = smb_time_audit_notify_watch,
2030         .chflags_fn = smb_time_audit_chflags,
2031         .file_id_create_fn = smb_time_audit_file_id_create,
2032         .streaminfo_fn = smb_time_audit_streaminfo,
2033         .get_real_filename_fn = smb_time_audit_get_real_filename,
2034         .connectpath_fn = smb_time_audit_connectpath,
2035         .brl_lock_windows_fn = smb_time_audit_brl_lock_windows,
2036         .brl_unlock_windows_fn = smb_time_audit_brl_unlock_windows,
2037         .brl_cancel_windows_fn = smb_time_audit_brl_cancel_windows,
2038         .strict_lock_fn = smb_time_audit_strict_lock,
2039         .strict_unlock_fn = smb_time_audit_strict_unlock,
2040         .translate_name_fn = smb_time_audit_translate_name,
2041         .fget_nt_acl_fn = smb_time_audit_fget_nt_acl,
2042         .get_nt_acl_fn = smb_time_audit_get_nt_acl,
2043         .fset_nt_acl_fn = smb_time_audit_fset_nt_acl,
2044         .chmod_acl_fn = smb_time_audit_chmod_acl,
2045         .fchmod_acl_fn = smb_time_audit_fchmod_acl,
2046         .sys_acl_get_file_fn = smb_time_audit_sys_acl_get_file,
2047         .sys_acl_get_fd_fn = smb_time_audit_sys_acl_get_fd,
2048         .sys_acl_set_file_fn = smb_time_audit_sys_acl_set_file,
2049         .sys_acl_set_fd_fn = smb_time_audit_sys_acl_set_fd,
2050         .getxattr_fn = smb_time_audit_getxattr,
2051         .fgetxattr_fn = smb_time_audit_fgetxattr,
2052         .listxattr_fn = smb_time_audit_listxattr,
2053         .flistxattr_fn = smb_time_audit_flistxattr,
2054         .removexattr_fn = smb_time_audit_removexattr,
2055         .fremovexattr_fn = smb_time_audit_fremovexattr,
2056         .setxattr_fn = smb_time_audit_setxattr,
2057         .fsetxattr_fn = smb_time_audit_fsetxattr,
2058         .aio_force_fn = smb_time_audit_aio_force,
2059 };
2060
2061
2062 NTSTATUS vfs_time_audit_init(void);
2063 NTSTATUS vfs_time_audit_init(void)
2064 {
2065         audit_timeout = (double)lp_parm_int(-1, "time_audit", "timeout",
2066                                             10000) / 1000.0;
2067         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "time_audit",
2068                                 &vfs_time_audit_fns);
2069 }