-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmvfs_mdki.h
1522 lines (1305 loc) · 40.7 KB
/
mvfs_mdki.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef MVFS_MDKI_H_
#define MVFS_MDKI_H_
/*
* Copyright (C) 1999, 2013 IBM Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* Author: IBM Corporation
* This module is part of the IBM (R) Rational (R) ClearCase (R)
* Multi-version file system (MVFS).
* For support, please visit http://www.ibm.com/software/support
*/
#include <linux/types.h>
#include <linux/param.h>
#include <linux/time.h>
#include <linux/in.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#include <linux/exportfs.h>
#include <linux/hash.h>
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
#include <linux/sched.h>
#else
#include <linux/cred.h>
#endif
#define MDKI_PTR_TYPE(name) struct name ## _struct *name
#define MDKI_GEN_TYPE(name) struct name ## _struct name
/*
* types, macros, functions, etc. which are exported from the adapter
* to the MVFS core.
*/
/*
* VATTR definitions and macros.
* Linux stores attributes in struct inode, not in separate objects.
* Our glue layers need to pull up attributes into an inode whenever
* it's returned to a linux kernel caller.
* We define our own struct vattr for internal use, and convert it to
* struct iattr (when setting underlying attributes) or copy it up into
* the inode (when returning values).
*/
struct mvfs_linux_vattr; /* forward decl */
#define VATTR_T struct mvfs_linux_vattr
#define VATTR_MODE_T mode_t /* mode as stored in vattr struct */
#define VATTR_UID_T uid_t /* UID as stored in vattr struct */
#define VATTR_GID_T gid_t /* GID as stored in vattr struct */
#define VATTR_SIZE_T loff_t /* Size data type */
#define VNODE_FMT_VATTR_SIZE_T_X "llx"
#define VNODE_FMT_VATTR_SIZE_T_D "lld"
#define VATTR_TIME_T time_t /* Time data type */
/*
* Attributes of interest to the caller of setattr or getattr.
*/
#undef AT_TYPE
#undef AT_MODE
#undef AT_UID
#undef AT_GID
#undef AT_FSID
#undef AT_NODEID
#undef AT_NLINK
#undef AT_SIZE
#undef AT_ATIME
#undef AT_MTIME
#undef AT_CTIME
#undef AT_RDEV
#undef AT_BLKSIZE
#undef AT_NBLOCKS
#define AT_TYPE 0x0001
#define AT_MODE 0x0002
#define AT_UID 0x0004
#define AT_GID 0x0008
#define AT_FSID 0x0010
#define AT_NODEID 0x0020
#define AT_NLINK 0x0040
#define AT_SIZE 0x0080
#define AT_ATIME 0x0100
#define AT_MTIME 0x0200
#define AT_CTIME 0x0400
#define AT_RDEV 0x0800
#define AT_BLKSIZE 0x1000
#define AT_NBLOCKS 0x2000
/*
* These are not really attributes, but flags that Linux uses to
* control the access checking. I will put these in the upper part
* of the word.
*/
#define AT_ATIME_SET 0x20000000
#define AT_MTIME_SET 0x40000000
#define AT_ALL (AT_TYPE|AT_MODE|AT_UID|AT_GID|AT_FSID|AT_NODEID|\
AT_NLINK|AT_SIZE|AT_ATIME|AT_MTIME|AT_CTIME|\
AT_RDEV|AT_BLKSIZE|AT_NBLOCKS)
/* The following is the same as AT_ALL but it excludes the FSID (dev) field */
#define AT_ALLNODEV (AT_ALL & ~AT_FSID)
#define AT_STAT (AT_MODE|AT_UID|AT_GID|AT_FSID|AT_NODEID|AT_NLINK|\
AT_SIZE|AT_ATIME|AT_MTIME|AT_CTIME)
#define AT_TIMES (AT_ATIME|AT_MTIME|AT_CTIME)
#define AT_NOSET (AT_NLINK|AT_FSID|AT_NODEID|AT_TYPE|AT_BLKSIZE|AT_NBLOCKS)
#define VATTR_NULL(vap) BZERO((vap), sizeof *(vap))
#define VATTR_GET_MASK(vap) ((vap)->va_mask)
#define VATTR_SET_MASK(vap, mask) (vap)->va_mask = (mask)
#define VATTR_GET_TYPE(vap) ((vap)->va_type)
#define VATTR_SET_TYPE(vap, vtype) ((vap)->va_type = (vtype))
#define VATTR_GET_MODE(vap) ((vap)->va_mode & ~S_IFMT)
#define VRIGHTSMASK ( S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO )
#define VATTR_SET_MODE_RIGHTS(vap, m) \
(vap)->va_mode = (VATTR_MODE_T)(((vap)->va_mode & ~VRIGHTSMASK) | ((m) & VRIGHTSMASK))
#define VATTR_SET_MODE_TYPE(vap, m) \
(vap)->va_mode = (VATTR_MODE_T)(((vap)->va_mode & VRIGHTSMASK) | ((m) & ~VRIGHTSMASK))
#define VATTR_GET_UID(vap) ((vap)->va_uid)
#define VATTR_SET_UID(vap, u) (vap)->va_uid = (VATTR_UID_T)(u)
#define VATTR_GET_GID(vap) ((vap)->va_gid)
#define VATTR_SET_GID(vap, gid) (vap)->va_gid = (VATTR_GID_T)(gid)
#define VATTR_GET_FSID(vap) ((vap)->va_fsid)
#define VATTR_SET_FSID(vap, fsidp) (vap)->va_fsid = *(fsidp)
#define VATTR_GET_NODEID(vap) ((vap)->va_nodeid)
#define VATTR_SET_NODEID(vap, nid) (vap)->va_nodeid = (nid)
#define VATTR_GET_NLINK(vap) ((vap)->va_nlink)
#define VATTR_SET_NLINK(vap, n) (vap)->va_nlink = (n)
#define VATTR_GET_SIZE(vap) ((vap)->va_size)
#define VATTR_SET_SIZE(vap, s) (vap)->va_size = (s)
#define VATTR_GET_BLKSIZE(vap) ((vap)->va_blksize)
#define VATTR_SET_BLKSIZE(vap, bs) (vap)->va_blksize = (bs)
#define VATTR_GET_NBLOCKS(vap) ((vap)->va_nblocks)
#define VATTR_SET_NBLOCKS(vap, nb) (vap)->va_nblocks = (nb)
/* Convert bytes to blocks - on Linux, the kstat block size is hardcoded
* as 512. See ST_NBLOCKSIZE in $COREUTILS/src/system.h, S_BLKSIZE in
* /usr/include/sys/stat.h, and especially the code in inode_add_bytes()
* in $LINUX/fs/stat.c.
*/
#define VATTR_BTODB(n) (((n) + 512 - 1) >> 9)
#define VATTR_GET_ATIME(vap) ((vap)->va_atime.tv_sec)
#define VATTR_GET_ATIME_TV(vap, tvp) *(tvp) = (vap)->va_atime
#define VATTR_GET_ATIME_TS(vap, tsp) MDKI_TIMEVAL_TO_TIMESPEC(&(vap)->va_atime, tsp)
#define VATTR_SET_ATIME_TV(vap, tvp) (vap)->va_atime = *(tvp)
#define VATTR_SET_ATIME_TS(vap, tsp) MDKI_TIMESPEC_TO_TIMEVAL(tsp, &(vap)->va_atime)
#define VATTR_GET_MTIME(vap) ((vap)->va_mtime.tv_sec)
#define VATTR_GET_MTIME_TV(vap, tvp) *(tvp) = (vap)->va_mtime
#define VATTR_GET_MTIME_TS(vap, tsp) MDKI_TIMEVAL_TO_TIMESPEC(&(vap)->va_mtime, tsp)
#define VATTR_SET_MTIME_VATTR(vap1, vap2) (vap1)->va_mtime = (vap2)->va_mtime
#define VATTR_SET_MTIME_TV(vap, tvp) (vap)->va_mtime = *(tvp)
#define VATTR_SET_MTIME_TS(vap, tsp) MDKI_TIMESPEC_TO_TIMEVAL(tsp, &(vap)->va_mtime)
#define VATTR_GET_CTIME(vap) ((vap)->va_ctime.tv_sec)
#define VATTR_GET_CTIME_TV(vap, tvp) *(tvp) = (vap)->va_ctime
#define VATTR_GET_CTIME_TS(vap, tsp) MDKI_TIMEVAL_TO_TIMESPEC(&(vap)->va_ctime, tsp)
#define VATTR_SET_CTIME_TV(vap, tvp) (vap)->va_ctime = *(tvp)
#define VATTR_SET_CTIME_TS(vap, tsp) MDKI_TIMESPEC_TO_TIMEVAL(tsp, &(vap)->va_ctime)
#define VATTR_GET_RDEV(vap) ((vap)->va_rdev)
#define VATTR_SET_RDEV(vap, dev) (vap)->va_rdev = (dev)
#define VATTR_FILL(vap) 0 /* nothing to do */
#define MDKI_TIMESPEC_TO_TIMEVAL(tsp, tvp) { \
(tvp)->tv_sec = (tsp)->tv_sec; \
(tvp)->tv_usec = (tsp)->tv_nsec / 1000; \
}
#define MDKI_TIMEVAL_TO_TIMESPEC(tvp, tsp) { \
(tsp)->tv_sec = (tvp)->tv_sec; \
(tsp)->tv_nsec = (tvp)->tv_usec * 1000; \
}
typedef enum vcexcl {
NONEXCL, EXCL
} VCEXCL_T;
typedef enum symfollow {
NO_FOLLOW, FOLLOW_LINK
} SYMFOLLOW_T;
#define VNODE_LF_LOOKUP (1 << 0)
#define VNODE_LF_AUDIT (1 << 1)
#define VNODE_NFS_FH_TYPE_RESERVED 0
#define VNODE_NFS_FH_TYPE_ERROR 255 /* see <linux/fs.h> dentry_to_fh() */
#define VFS_T struct vfs
#define VFSOPS_T struct vfsops
#define VNODE_T struct mdki_vnode
#define V_OP_T struct vnodeops
#include <linux/statfs.h>
#define LINUX_STATFS_T struct kstatfs
#define STATVFS_T LINUX_STATFS_T
typedef u_short mdki_vtype_t;
#define VTYPE_T mdki_vtype_t
#define VNON 0
#define VREG 1
#define VDIR 2
#define VBLK 3
#define VCHR 4
#define VLNK 5
#define VFIFO 6
#define VSOCK 7
#define VBAD 8
struct vfs;
struct vfsops;
struct mdki_vnode;
struct vnodeops;
#define MVFS_MAJOR_T int
#define MOFFSET_T loff_t
#define MVFS_FMT_MOFFSET_T_X KS_FMT_OFF_T_X
#define MVFS_FMT_MOFFSET_T_D KS_FMT_OFF_T_D
#define MVFS_VFSISMVFS(vfsp, mfs_vfsopp) ((vfsp)->vfs_fstype == VFS_MVFS)
/* mvfs_linux_utils.c */
extern void
mdki_mark_vfs_dirty(VFS_T *vfsp);
extern void
mdki_inactive_finalize(VNODE_T *vp);
extern int
mdki_linux_statvfs_vnode(
VNODE_T *cvn,
STATVFS_T *sbp
);
extern int
init_mvfs_module(void);
extern void
cleanup_mvfs_module(void);
enum uio_rw {UIO_READ, UIO_WRITE};
typedef enum uio_rw uio_rw_t;
typedef struct iovec iovec_t;
typedef int mdki_boolean_t;
/*
* UIO definitions.
* This is either really ugly or a clever hack, your choice. Linux doesn't
* have a uio structure per-se. It handles user I/O in a more ad-hoc manner.
* At least for readdir, and probably for other functions as well, there
* isn't a good mapping. In readdir, we are called with a pointer to an
* opaque data buffer and a pointer to a function to fill it in. However,
* mfs_readdir expects a pointer to a uio structure and does the actual
* I/O from the lowest levels. What I will do is to define a uio structure
* that contains offsets that correspond roughly to a standard uio structure
* and add to it useful offsets for Linux. The various UIO macros will
* then take care of doing the right thing for their requirements.
*/
typedef struct uio {
iovec_t *uio_iov; /* List of iovectors */
int uio_iovcnt; /* Number of iovectors in list */
/* First we add the canonical offsets as needed */
int uio_resid; /* residual count */
loff_t uio_offset; /* File offset */
int uio_segflg; /* segment flag - location of I/O buf */
/* Then we add our extra stuff as needed. This could become
* a union structure here if this gets too unwieldy.
*/
void *uio_buff; /* opaque buffer */
void *uio_func; /* pointer to function to use */
mdki_boolean_t uio_rddir_full; /* TRUE if readdir filled the buffer */
} uio_t;
#define UIO_USERSPACE 1
#define UIO_SYSSPACE 2
/*
* MVFS_LINUX_MAXRPCDATA is the maximum size for RPC data. This is used
* in linux_fop_readdir to set the buffer size when making the readdir
* call. It is also used in mvfs_mdep_linux.c when setting up the
* table of rpc reply sizes.
*/
#define MVFS_LINUX_MAXRPCDATA 8192
extern int
mdki_linux_readlink_uiomove(
char *from,
int cnt,
int uio_flag,
uio_t *uiop
);
/* A debug tool that Linux doesn't define for the kernel
*/
extern void
mdki_assfail(
const char *fmt,
const char *asserted_str,
const char *filename,
const char *funcname,
int lineno
) __attribute__((noreturn));
typedef struct mvfs_linux_vattr {
u_int va_mask; /* Bit mask of attributes */
VTYPE_T va_type; /* Vnode type (mode & S_IFMT) */
VATTR_MODE_T va_mode; /* file access mode (& ~S_IFMT) */
VATTR_UID_T va_uid; /* owner user id */
VATTR_GID_T va_gid; /* owner group id */
dev_t va_fsid; /* file system id (dev for now) */
dev_t va_rdev; /* device the file represents */
u_long va_nodeid; /* node id */
u_long va_nlink; /* number of links to file */
VATTR_SIZE_T va_size; /* file size in bytes */
struct timeval va_atime; /* access time */
struct timeval va_mtime; /* mod time */
struct timeval va_ctime; /* change vnode time */
u_long va_blksize; /* block size */
u_long va_nblocks; /* allocation size in blocks */
} vattr_t;
typedef struct semaphore mdki_sleeplock_t;
/*
* should ISLOCKED count sema.waking as available?
* I'd say no, since if it's set it means that someone is about to wake up
* and get the lock anyway.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
# define MDKI_SLEEP_ISLOCKED(semap) (atomic_read(&(semap)->count) < 1)
#else
# define MDKI_SLEEP_ISLOCKED(semap) ((semap)->count < 1)
#endif
#define MDKI_SLEEP_LOCK(semap) down(semap)
#define MDKI_SLEEP_UNLOCK(semap) up(semap)
#define MDKI_SLEEP_TRYLOCK(semap) down_trylock(semap)
# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
# define MDKI_INIT_SLEEPLOCK(semap) init_MUTEX(semap)
# define MDKI_DECLARE_SLEEPLOCK(name) DECLARE_MUTEX(name)
# else
# define MDKI_INIT_SLEEPLOCK(semap) sema_init(semap, 1)
# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
# define MDKI_DECLARE_SLEEPLOCK(name) DEFINE_SEMAPHORE(name, 1)
# else
# define MDKI_DECLARE_SLEEPLOCK(name) DEFINE_SEMAPHORE(name)
# endif /* else < KERNEL_VERSION(2,6,36) */
# endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) */
#define MDKI_FREE_SLEEPLOCK(semap) /* nothing to do */
extern void
mdki_makevfsdev(
VFS_T *vfsp,
int major,
int minor,
int nvmajor,
int nvminor
);
extern int
mdki_vfs_to_dev(VFS_T *vfsp);
extern int
mdki_vcount(VNODE_T *vp);
#define V_COUNT(vp) mdki_vcount(vp)
extern VNODE_T *
mdki_vn_hold(VNODE_T *vp);
#ifdef MVFS_DEBUG
extern VNODE_T *
mdki_debug_vn_hold(
VNODE_T *vp,
char *file,
const char *function,
int line
);
#define VN_HOLD(vp) mdki_debug_vn_hold(vp, __FILE__, __func__, __LINE__)
#else
#define VN_HOLD(vp) mdki_vn_hold(vp)
#endif
/* The following is a debug version of this. The do {...} while(0)
* construct is to prevent compile errors in code fragments like this
* if (vw) VN_RELE(vw);
* (This can be an inline macro because it returns no value.)
*/
#ifdef MVFS_DEBUG
#define VN_RELE(vp) do { \
ASSERT(vp != NULL); \
MDKI_TRACE(TRACE_VNODES,"mdki_vn_rele %s:%s:%d, vp=%p cnt=--%d\n", \
__FILE__, __func__, __LINE__, vp, V_COUNT(vp)); \
ASSERT(V_COUNT(vp) != 0); \
mdki_vn_rele(vp); \
} while (0)
#else
#define VN_RELE(vp) mdki_vn_rele(vp)
#endif
#define REAL_VN_RELE(vp) mdki_vn_rele(vp)
extern void
mdki_vn_rele(VNODE_T *vp);
extern mdki_boolean_t
mdki_vpismfs(VNODE_T *vp);
extern void
mdki_decrement_link(VNODE_T *vp);
extern void
mdki_increment_link(VNODE_T *vp);
#if 0 /* disable, it won't work for NFS */
extern void
mdki_linux_stop_paging(
VNODE_T *vp
);
extern void
mdki_linux_start_paging(
VNODE_T *vp
);
#endif
#define FLAG_NODATASYNC 0 /* conversion of our flags to theirs */
#define FLAG_DATASYNC 1
struct unlink_ctx;
extern mdki_boolean_t
mdki_linux_rename_needed(
VNODE_T *vp,
struct unlink_ctx * context
);
extern VNODE_T *
mdki_make_sysroot_vnode(void);
extern void
mdki_linux_release_majors(MVFS_MAJOR_T *tbl);
extern void
mdki_release_sysroot_vnode(VNODE_T *sysrootvp);
#define MVFS_CVP_TO_VP(cvp) (cvp)
#define CVN_CMP(vp1, vp2) ((vp1) == (vp2) || \
((vp1)->v_dent == (vp2)->v_dent && \
(vp1)->v_vfsmnt == (vp2)->v_vfsmnt))
extern int
mvop_linux_realvp(
VNODE_T *vp,
VNODE_T **rvp
);
extern void
mdki_make_dcache(
VNODE_T *dvp,
VNODE_T *vp,
const char *nm
);
extern void
mdki_rm_dcache(
VNODE_T *vp
);
extern void
mdki_start_flush_dcache(
VNODE_T *vp,
void **arg
);
extern mdki_boolean_t
mdki_finish_flush_dcache(
void *arg
);
extern MVFS_MAJOR_T
mdki_linux_get_major(void);
extern void
mdki_linux_release_majors(
MVFS_MAJOR_T *tbl
);
extern int
mdki_makedevice(
int major,
int minor
);
extern int
mdki_major(
int dev
);
extern int
mdki_minor(
int dev
);
/* hook to clean up attributes in inode whenever we get them */
extern void
mdki_linux_vattr_pullup(
VNODE_T *vp,
VATTR_T *vap,
int mask
);
extern int
mdki_sync_size(
VNODE_T *vp,
loff_t size,
int actual
);
extern int
mdki_set_modified(
VNODE_T *vp,
VATTR_T *vap
);
extern int
mdki_set_accessed(
VNODE_T *vp,
VATTR_T *vap
);
extern int
mdki_set_ichg(
VNODE_T *vp,
VATTR_T *vap
);
/* FIXME: We need to look at these routines. They can cause faults. */
#define COPYIN(from,to,count) \
mdki_copy_from_user((to),(from),(unsigned long)(count))
#define COPYOUT(from,to,count) \
mdki_copy_to_user((to),(from),(unsigned long)(count))
#define REAL_KMEM_ALLOC(bsize,flag) mdki_linux_kmalloc((bsize),(flag))
#define REAL_KMEM_FREE(ptr,bsize) mdki_linux_kfree((ptr),(bsize))
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
#define MVFS_KMEM_CACHE_T kmem_cache_t
#else
#define MVFS_KMEM_CACHE_T struct kmem_cache
#endif
#ifndef KMEMDEBUG
#define KMEM_ALLOC(bsize,flag) REAL_KMEM_ALLOC(bsize,flag)
#define KMEM_FREE(ptr,bsize) { REAL_KMEM_FREE(ptr,bsize); (ptr) = NULL; }
#define STRFREE(str) { REAL_KMEM_FREE((str),0); (str) = NULL; }
#define STRDUP(str) mfs_strdup(str)
#else /* KMEMDEBUG */
#define KMEM_ALLOC(bsize,flag) mfs_kalloc(bsize, flag, mdki_getreturn(),mdki_getmycaller())
#define KMEM_FREE(ptr,bsize) \
{ mfs_kfree(ptr,bsize,mdki_getreturn(),mdki_getmycaller()); (ptr) = NULL; }
#define STRDUP(str) mfs_kmstrdup(str, mdki_getreturn(),mdki_getmycaller())
#define STRFREE(str) \
{ mfs_kfree(str, STRLEN(str)+1, mdki_getreturn(),mdki_getmycaller()); (str) = NULL; }
#endif /* KMEMDEBUG */
#define KM_SLEEP 1
#define KM_NOSLEEP 0
#define KM_PAGED 0 /* to be ORed with others */
extern int
mdki_linux_page_size(void);
extern void
mdki_linux_panic(
const char *fmt,
...
) __attribute__((noreturn, format (printf, 1, 2)));
extern const char *mdki_panicstr;
extern void
mdki_invalidate_vnode_pages(VNODE_T *vp);
/* Credentials */
/* Linux doesn't have a real cred structure. They have file system
* creds stored in the task structure. We will make our own structure
* and fill it in as needed.
* Actually as of the 2.6.32 kernel, it has a cred structure but we still
* have problems if we use it because it contains pointers to sub-structures
* like the group_info structure which also have counters in them. Some of
* these substructures do not provide easy accessor functions for us to use.
* So to keep from artificially elevating counts, and possible causing them
* to wrap if we cache them in a long lived mnode, we still make our own copy.
* in the mnode without worry.
*/
typedef struct vnode_cred {
atomic_t cr_ref; /* reference count */
uid_t cr_euid; /* effective user id */
gid_t cr_egid; /* effective group id */
uid_t cr_ruid; /* real user id */
gid_t cr_rgid; /* real group id */
uid_t cr_suid; /* "saved" user id (from exec) */
gid_t cr_sgid; /* "saved" group id (from exec) */
uid_t cr_fsuid; /* file system user id */
gid_t cr_fsgid; /* file system group id */
unsigned int cr_ngroups; /* number of groups in cr_groups */
gid_t cr_groups[0];
} vnode_cred_t;
#define CRED_T vnode_cred_t
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
/* Starting in the 2.6.32 kernel, Linux does have it's own cred structure
* so provide a definition to use when we need to point to it
*/
#define SYS_CRED_T struct cred
#endif
#define CRED_UID_T uid_t
#define CRED_GID_T gid_t
#if defined(MVFS_DEBUG) || defined(MVFS_LOG)
extern CRED_T *
mdki_dup_default_creds(
const char *file,
const char *func,
int line
);
extern CRED_T *
mdki_crdup(
CRED_T *cred,
const char *file,
const char *func,
int line
);
extern void
mdki_crfree(
CRED_T *cred,
const char *file,
const char *func,
int line
);
extern void
mdki_crhold(
CRED_T *cred,
const char *file,
const char *func,
int line
);
/* For now, we will always copy the creds from the task structure */
#define MDKI_GET_UCRED() MDKI_DUP_UCRED()
#define MDKI_DUP_UCRED() mdki_dup_default_creds(__FILE__, __func__, __LINE__)
#define MDKI_CRDUP(c) mdki_crdup(c, __FILE__, __func__, __LINE__)
#define MDKI_CRFREE(c) mdki_crfree(c, __FILE__, __func__, __LINE__)
#define MDKI_CRHOLD(c) mdki_crhold(c, __FILE__, __func__, __LINE__)
#else
extern CRED_T *
mdki_dup_default_creds(void);
extern CRED_T *
mdki_crdup(CRED_T *cred);
extern void
mdki_crfree(CRED_T *cred);
extern void
mdki_crhold(CRED_T *cred);
/* For now, we will always copy the creds from the task structure */
#define MDKI_GET_UCRED() MDKI_DUP_UCRED()
#define MDKI_DUP_UCRED() mdki_dup_default_creds()
#define MDKI_CRDUP(c) mdki_crdup(c)
#define MDKI_CRFREE(c) mdki_crfree(c)
#define MDKI_CRHOLD(c) mdki_crhold(c)
#endif
#define MDKI_CR_GET_UID(c) (c)->cr_fsuid
#define MDKI_CR_GET_GID(c) (c)->cr_fsgid
#define MDKI_CR_GET_GRPLIST(c) (c)->cr_groups
#define MDKI_CR_END_GRPLIST(c) &(c)->cr_groups[(c)->cr_ngroups]
/* We want to check the file system UID, not the true effective UID */
#define MDKI_CR_IS_SETUID_ROOT(c) ((c)->cr_fsuid == MDKI_ROOT_UID && (c)->cr_ruid != MDKI_ROOT_UID)
#define MDKI_CR_SET_E2RUID(c) (c)->cr_fsuid = (c)->cr_ruid
#define MDKI_CR_SET_E2ROOTUID(c) (c)->cr_fsuid = MDKI_ROOT_UID
#define MDKI_CR_IS_ROOT(c) ((c)->cr_fsuid == MDKI_ROOT_UID)
#define MDKI_CR_SIZE(c) (sizeof(CRED_T) + ((c)->cr_ngroups * sizeof(gid_t)))
#define MDKI_CR_EQUAL(c1,c2) \
(((c1)->cr_ngroups == (c2)->cr_ngroups) && \
(BCMP(&(c1)->cr_euid, &(c2)->cr_euid, \
(MDKI_CR_SIZE(c1) - sizeof((c1)->cr_ref))) == 0))
#define MDKI_ROOT_UID 0
#define MDKI_ROOT_GID 0
#define VNODE_LASTCLOSE_T int
#define VNODE_LASTCLOSE_COUNT 0
#define VNODE_NOT_LASTCLOSE_COUNT 1
extern int
mdki_linux_proc_setview(
VNODE_T *vw,
VNODE_T *viewdir,
const char *viewname,
int *status_ok
);
extern VNODE_T *
mdki_linux_get_procview(void);
extern VNODE_T *
mdki_get_urdir_vnode(void);
extern VNODE_T *
mdki_get_ucdir_vnode(void);
static inline const char *
mdki_get_ucomm_ptr(void)
{
return(current->comm);
}
static inline int
mdki_get_ucmask(void)
{
return(current->fs->umask);
}
extern int
mdki_linux_readdir_uiomove(
char *from,
int cnt,
int uio_flag,
uio_t *uiop,
loff_t offset
);
struct lookup_ctx;
extern int
mvop_linux_lookup_component(
VNODE_T *dvp,
char *nm,
VNODE_T **vpp,
CRED_T *cred,
struct lookup_ctx * ctx
);
extern void
mdki_get_rootdir(void *ctx);
extern int
mdki_linux_maxnamelen(void);
extern int
mdki_linux_maxpathlen(void);
/*
* MVOP routines which need our type definitions
*/
extern int
mvop_linux_open_kernel(
VNODE_T **vpp, /* call/return */
int flags,
CRED_T *cred,
void **filp /* RETURN */
);
extern int
mvop_linux_close_kernel(
VNODE_T *vp,
int flags,
VNODE_LASTCLOSE_T count,
MOFFSET_T off,
CRED_T *cred,
void *filp,
fl_owner_t owner_id
);
extern int
mvop_linux_read_kernel(
struct uio *uiop,
int flags,
CRED_T *cred,
char *filp
);
extern ssize_t
mvop_linux_write_kernel(
struct uio *uiop,
int flags,
CRED_T *cred,
char *filp
);
extern int
mvop_linux_lookup_ioctl(
/* mfs_pn_char_t */char *path,
int segflag,
SYMFOLLOW_T follow,
VNODE_T **dvpp,
VNODE_T **vpp,
CRED_T *cred
);
extern int
mvop_linux_lookup_storage_file(
char *path,
VNODE_T **vpp, /* return */
CRED_T *cred
);
extern int
mvop_linux_fsync_kernel(
VNODE_T *vp,
int flag,
CRED_T *cred,
void *filp
);
/* read/write/access flags */
#define VREAD 0400
#define VWRITE 0200
#define VEXEC 0100
#define FREAD 0x0001
#define FWRITE 0x0002
#define FCREAT 0x1000
#define FTRUNC 0x2000
#define FAPPEND 0x4000
/* undefine them, IA64 defines them to no good end */
#undef MAP_SHARED
#undef PROT_READ
#undef PROT_WRITE
#undef PROT_EXEC
#define MAP_SHARED 0x00000001
#define PROT_READ VREAD
#define PROT_WRITE VWRITE
#define PROT_EXEC VEXEC
extern VFS_T *mdki_logging_vfsp;
extern void
mdki_set_clrvnode_vfsp(VFS_T *vfsp);
extern void
mdki_clear_clrvnode_vfsp(VFS_T *vfsp);
extern void
mdki_set_logging_vfsp(VFS_T *vfsp);
extern void
mdki_clear_logging_vfsp(VFS_T *vfsp);
extern void
mdki_set_looproot_vp(VNODE_T *vp);
extern void
mdki_clear_looproot_vp(VNODE_T *vp);
#define MDKI_VFS_LOG(level, str, ...) { \
if (mdki_logging_vfsp != NULL) \
VFS_LOG(mdki_logging_vfsp, level, str, __VA_ARGS__); \
else \
mdki_linux_printf(str, __VA_ARGS__); \
}
#define LOG_PROBLEM(str) MDKI_VFS_LOG(VFS_LOG_ERR,"%s: " str "\n", __func__ )
#define NOT_IMPLEMENTED() LOG_PROBLEM("not implemented yet")
#define VOPBD_T void
#define ROOTDIR_T int
#define TRACE_VNODES 0x00000001
#define TRACE_DCACHE 0x00000002
#define TRACE_XDR 0x00000004
#define TRACE_USERLOOKUP 0x00000008
#define TRACE_PNLOOKUP 0x00000010
#define TRACE_RPC 0x00000020
#define TRACE_CREDS 0x00000040
#define TRACE_RDWR 0x00000080
#define TRACE_OPEN 0x00000100
#define TRACE_CLOSE 0x00000200
#define TRACE_MAP 0x00000400
#define TRACE_ACCESS 0x00000800
#define TRACE_GETATTR 0x00001000
#define TRACE_SETATTR 0x00002000
#define TRACE_INACTIVE 0x00004000
#define TRACE_READDIR 0x00008000
#define TRACE_REMOVE 0x00010000
#define TRACE_VFSMNT 0x00020000
#define TRACE_PROC 0x00040000
extern unsigned int mdki_tracing;
#if defined(MVFS_DEBUG) || defined(MVFS_LOG)
#define MDKI_TRACE(subsys, fmt, ...) do { \
if ((mdki_tracing & (subsys)) != 0) \
MDKI_VFS_LOG(VFS_LOG_DEBUG, #subsys ": " fmt, __VA_ARGS__); \
} while (0)
#else /* no logging */
#define MDKI_TRACE(subsys, fmt, ...) /*nothing*/
#endif
/*
* Make sure we can see "static" symbols
* (if really static, kernel debugger doesn't have them)
*/
#ifdef MVFS_DEBUG
#undef STATIC
#define STATIC /**/
#else
#define STATIC static
#endif
extern caddr_t
mdki_getreturn(void);
extern caddr_t
mdki_getmycaller(void);
extern caddr_t
mdki_getmycallerscaller(void);
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define MVFS_MAXOFF_T 0x7fffffffffffffffLL
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
# define MDKI_TASKLIST_LOCK() read_lock(&tasklist_lock)
# define MDKI_TASKLIST_UNLOCK() read_unlock(&tasklist_lock)
#else
# define MDKI_TASKLIST_LOCK() rcu_read_lock()
# define MDKI_TASKLIST_UNLOCK() rcu_read_unlock()
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
# define MDKI_GET_CURRENT_FSUID() current->fsuid
# define MDKI_GET_CURRENT_FSGID() current->fsgid
# define MDKI_GET_CURRENT_EUID() current->euid
# define MDKI_GET_CURRENT_EGID() current->egid
# define MDKI_GET_CURRENT_UID() current->uid
# define MDKI_GET_CURRENT_GID() current->gid
# define MDKI_GET_CURRENT_SUID() current->suid
# define MDKI_GET_CURRENT_SGID() current->sgid
#else
# define MDKI_GET_CURRENT_FSUID() current_fsuid()
# define MDKI_GET_CURRENT_FSGID() current_fsgid()
# define MDKI_GET_CURRENT_EUID() current_euid()
# define MDKI_GET_CURRENT_EGID() current_egid()
# define MDKI_GET_CURRENT_UID() current_uid()
# define MDKI_GET_CURRENT_GID() current_gid()
# define MDKI_GET_CURRENT_SUID() current_suid()
# define MDKI_GET_CURRENT_SGID() current_sgid()
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
/*
* Use d_set_d_op instead of direct assigment,
* so we don't need to adjust the various flags.
*/
#if defined(MRG) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,25))
# define MDKI_SET_DOPS(D, OPS) do {\
seq_spin_lock(&(D)->d_lock);\
d_set_d_op((D), (OPS));\
seq_spin_unlock(&(D)->d_lock);\
} while(0)
#else /* defined(MRG) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,25)) */
# define MDKI_SET_DOPS(D, OPS) do {\
spin_lock(&(D)->d_lock);\
d_set_d_op((D), (OPS));\
spin_unlock(&(D)->d_lock);\
} while(0)
#endif /* else defined(MRG) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,25)) */
#define MDKI_UNSET_DOPS(D) do {(D)->d_flags &= ~(DCACHE_OP_HASH | \
DCACHE_OP_COMPARE | \
DCACHE_OP_REVALIDATE | \
DCACHE_OP_DELETE); \
(D)->d_op = NULL; \
}while(0)
#else
#define MDKI_SET_DOPS(D, OPS) (D)->d_op = (OPS)
#define MDKI_UNSET_DOPS(D) MDKI_SET_DOPS((D), NULL)
#endif
typedef MDKI_GEN_TYPE(vnode_kdirent_t);
#define KDIRENT_T vnode_kdirent_t
#define KDIRENT_BASESIZE (mdki_dirent_basesize())
#define KDIRENT_RECLEN(namelen) mdki_linux_dirent_reclen(namelen)
#define KDIRENT_INIT(dentp, ino, nm, nmlen, next_offset) \
mdki_linux_dirent_init(dentp, ino, nm, nmlen, next_offset)