1/*
2 * Copyright 2016, NICTA
3 *
4 * This software may be distributed and modified according to the terms of
5 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
6 * See "LICENSE_GPLv2.txt" for details.
7 *
8 * @TAG(NICTA_GPL)
9 */
10
11#define VfsDirEmitR $ty:(LoopResult (#{dirctx: VfsDirContext}) (#{dirctx: VfsDirContext}))
12
13VfsDirEmitR vfs_dir_emit($ty:(VfsDirEmitP) args)
14{
15    VfsDirEmitR ret;
16    bool_t keep_going;
17
18    $ty:(VfsDirContext) cogent_ctx = args.dirctx;
19    struct dir_context *ctx = cogent_ctx->os;
20    ctx->pos = cogent_ctx->pos;
21
22    // printk ("vfs_dir_emit(name=%s(len=%d), ino=%u, type=%u)\n",
23    //          args.name->values, args.name->len, args.ino, args.ftype);
24    keep_going.boolean = dir_emit(ctx, args.name->values, args.name->len,
25                            args.ino, args.ftype);
26    
27    if (!keep_going.boolean) {
28        ret.tag = TAG_ENUM_Break;
29        ret.Break.dirctx = args.dirctx;
30    } else {
31        ret.tag = TAG_ENUM_Iterate;
32        ret.Iterate.dirctx = args.dirctx;
33    }
34
35    return ret;
36}
37
38
39$ty:((SysState, VfsInode)) vfs_inode_mark_dirty ($ty:((SysState, VfsInode)) args) {
40    // printk ("vfs_inode_mark_dirty: dirtied %p ino %d\n", &args.p2->vfs.inode_lin, args.p2->vfs.inode_lin.i_ino);
41    mark_inode_dirty (&(args.p2->vfs.inode_lin));
42    return args;
43}
44
45// shouldn't be re-entrnat?
46$ty:(R (SysState, VfsInode) (SysState, VfsInode)) vfs_inode_insert($ty:(#{ex: SysState, inode: VfsInode}) args)
47{
48    $ty:(R (SysState, VfsInode) (SysState, VfsInode)) ret;
49
50    if (insert_inode_locked (&(args.inode->vfs.inode_lin)) == 0) {
51        /* printk ("vfs_inode_insert: inserted %p ino %d\n", 
52                   &args.inode->vfs.inode_lin, 
53                   args.inode->vfs.inode_lin.i_ino);
54        */
55
56        ret.tag = TAG_ENUM_Success;
57        ret.Success.p1 = args.ex;
58        ret.Success.p2 = args.inode;
59    } else {
60        ret.tag = TAG_ENUM_Error;
61        ret.Error.p1 = args.ex;
62        ret.Error.p2 = args.inode;
63    }
64
65    return ret;
66}
67
68bool_t vfs_inode_is_sync_dir ($ty:(VfsInode!) inode) {
69    bool_t ret;
70    ret.boolean = IS_DIRSYNC (&(inode->vfs.inode_lin));
71    return ret;
72}
73
74bool_t vfs_inode_is_sync ($ty:(VfsInode!)inode) {
75    bool_t ret;
76    ret.boolean = IS_SYNC (&(inode->vfs.inode_lin));
77    return ret;
78}
79
80/*
81// FIXME: re-entrant, but may lock
82$ty:(RR (SysState, VfsInode) () U32) vfs_page_symlink ($ty:((SysState, VfsInode, CString!)) args) {
83    $ty:(RR (SysState, VfsInode) () U32) ret;
84    ret.p1.p1 = args.p1;
85    ret.p1.p2 = args.p2;
86
87    int err = page_symlink (&(args.p2->vfs.inode_lin), args.p3->values, args.p3->len);
88    if (err) {
89        ret.p2.tag = TAG_ENUM_Error;
90        ret.p2.Error = err;
91    } else {
92        ret.p2.tag = TAG_ENUM_Success;
93    }
94
95    return ret;
96}
97*/
98
99$ty:(VfsInode) vfs_inode_link_device ($ty:((VfsInode, VfsMode, #VfsDevice)) args) {
100    init_special_inode (&(args.p1->vfs.inode_lin), args.p2, args.p3);
101    return args.p1;
102}
103
104$ty:(#VfsDevice) vfs_create_device ($ty:((VfsDeviceMajor, VfsDeviceMinor)) args) {
105    return MKDEV (args.p1, args.p2);
106}
107
108$ty:((VfsDeviceMajor, VfsDeviceMinor)) vfs_device_inspect ($ty:(#VfsDevice) dev) {
109    $ty:((VfsDeviceMajor, VfsDeviceMinor)) ret = {.p1 = MAJOR(dev), .p2 = MINOR(dev)};
110    return ret;
111}
112
113$ty:((SysState, OSTimeSpec)) os_get_current_fs_time($ty:((SysState, VfsInode!)) args)
114{
115    $ty:((SysState, OSTimeSpec)) ret;
116    struct inode *inode = &(args.p2->vfs.inode_lin);
117
118$escstm:(#if LINUX_VERSION_CODE > KERNEL_VERSION(4,19,0))
119    struct timespec64 ts;
120
121    ktime_get_coarse_real_ts64(&ts);
122    struct timespec64 now = timespec64_trunc(ts, inode->i_sb->s_time_gran);
123$escstm:(#else)
124    struct timespec now = timespec_trunc(current_kernel_time(), inode->i_sb->s_time_gran);
125$escstm:(#endif)
126
127    ret.p2.tv_sec = now.tv_sec;
128    ret.p2.tv_nsec = now.tv_nsec;
129
130    ret.p1 = args.p1;
131
132    return ret;
133}
134