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#include <linux/version.h>
12#include <linux/init.h>
13#include <linux/slab.h>
14#include <linux/module.h>
15#include <linux/namei.h>
16#include <linux/ctype.h>
17#include <linux/parser.h>
18#include <linux/seq_file.h>
19#include <linux/mount.h>
20#include <bilbyfs.h>
21
22#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
23#include <uapi/linux/mount.h>
24#endif
25
26#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0)
27#define put_page(page) page_cache_release(page)
28#endif
29#if LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0)
30#define timespec64_trunc timespec_trunc
31#endif
32
33static int init_inode_by_type(struct backing_dev_info *bdi, struct inode *inode)
34{
35        int err = 0;
36
37        /* Disable read-ahead */
38#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
39        inode->i_mapping->backing_dev_info = bdi;
40#endif
41
42        switch (inode->i_mode & S_IFMT) {
43        case S_IFREG:
44                inode->i_mapping->a_ops = &bilbyfs_file_address_operations;
45                inode->i_op = &bilbyfs_file_inode_operations;
46                inode->i_fop = &bilbyfs_file_operations;
47                break;
48        case S_IFDIR:
49                inode->i_op  = &bilbyfs_dir_inode_operations;
50                inode->i_fop = &bilbyfs_dir_operations;
51                inode->i_size = BILBYFS_INODE_SZ;
52                break;
53        case S_IFLNK:
54	  /* Symlinks have data blocks handled through the page cache */
55	  //	        inode->i_mapping->a_ops = &bilbyfs_file_address_operations;
56                inode->i_op = &bilbyfs_symlink_inode_operations;
57		inode->i_link = NULL;
58                break;
59        case S_IFBLK:
60        case S_IFCHR:
61        case S_IFSOCK:
62        case S_IFIFO:
63                bilbyfs_err("Inode type not yet supported (%x)",
64                        (unsigned int)(inode->i_mode & S_IFMT));
65                err = -EINVAL;
66                break;
67        default:
68                bilbyfs_err("Unknown inode type. This should not happen!");
69                err = -EINVAL;
70                break;
71        }
72        return err;
73}
74
75static struct inode *bilbyfs_iget(struct bilbyfs_info *bi, unsigned long inum)
76{
77        struct inode *inode;
78        int err = 0;
79
80        inode = iget_locked(bi->vfs_sb, inum);
81        if (!inode)
82                return ERR_PTR(-ENOMEM);
83        if (!(inode->i_state & I_NEW))
84                return inode;
85        down(&bi->wd.lock);
86        err = fsop_iget(bi, inum, inode);
87        up(&bi->wd.lock);
88        if (!err) {
89                init_inode_by_type(bi->vfs_sb->s_bdi, inode);
90                unlock_new_inode(inode);
91                return inode;
92        }
93        bilbyfs_err("BilbyFsError: fsop_iget(ino=%lu) = %d\n", inum, err);
94        iget_failed(inode);
95        return ERR_PTR(err);
96}
97
98static struct dentry *bilbyfs_lookup(struct inode *dir, struct dentry *dentry,
99                                     unsigned int flags)
100{
101        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
102        struct inode *inode;
103        ino_t inum;
104        int err;
105
106        down(&bi->wd.lock);
107        err = fsop_lookup(bi, dir, dentry->d_name.name, &inum);
108        up(&bi->wd.lock);
109        if (err == -ENOENT) {
110                return NULL;
111        }
112        if (!err) {
113                inode = bilbyfs_iget(bi, inum);
114                if (!IS_ERR(inode)) {
115                        d_add(dentry, inode);
116                        return NULL;
117                }
118                err = PTR_ERR(inode);
119        }
120        bilbyfs_err("BilbyError: bilbyfs_lookup(dir.ino = %lu, name=%.*s, flags=%x)=%d\n", dir->i_ino, dentry->d_name.len, dentry->d_name.name, flags, err);
121        return ERR_PTR(err);
122}
123
124/* Allocates and initialises an inode.
125 * @dir: pointer to the directory inode, is NULL iff we allocate root.
126 * @mode: type + permissions of the inode
127 *
128 * The function returns a pointer to the inode or a negative error-code.
129 */
130static struct inode *bilbyfs_new_inode(struct super_block *sb,
131                                       struct inode *dir, umode_t mode)
132{
133        struct inode *inode;
134        int err;
135
136        bilbyfs_debug("bilbyfs_new_inode(mode = 0x%x)\n", mode);
137        inode = new_inode(sb);
138        if (!inode) {
139                bilbyfs_err("BilbyFsError: new_inode() = -ENOMEM");
140                return ERR_PTR(-ENOMEM);
141        }
142        /* FIXME: UBIFS has the following line that doesn't seem
143         * required, needs to be double checked
144         */
145        inode->i_mapping->nrpages = 0;
146        inode_init_perm(inode, dir, mode);
147        err = init_inode_by_type(sb->s_bdi, inode);
148        if (!err)
149                return inode;
150        make_bad_inode(inode);
151        iput(inode);
152        bilbyfs_err("BilbyFsError: bilbyfs_new_inode(mode = 0x%x) = %d\n", mode, err);
153        return ERR_PTR(err);
154}
155
156static int bilbyfs_link(struct dentry *old_dentry, struct inode *dir,
157                 struct dentry *dentry)
158{
159        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
160        int err;
161
162        down(&bi->wd.lock);
163        err = fsop_link(dir->i_sb->s_fs_info, old_dentry->d_inode, dir, dentry->d_name.name);
164        up(&bi->wd.lock);
165        if (!err) {
166                ihold(old_dentry->d_inode);
167                d_instantiate(dentry, old_dentry->d_inode);
168        } else
169          bilbyfs_err("BilbyFsError: bilbyfs_link() = %d\n", err);
170        return err;
171}
172
173static int bilbyfs_create(struct inode *dir, struct dentry *dentry,
174                          umode_t mode, bool excl)
175{
176        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
177        struct inode *inode;
178        int err;
179
180        bilbyfs_debug("bilbyfs_create (dir.ino = %lu, name=%.*s, mode=%x)\n", dir->i_ino, dentry->d_name.len, dentry->d_name.name, mode);
181        inode = bilbyfs_new_inode(dir->i_sb, dir, S_IFREG | mode);
182        if (IS_ERR(inode))
183                return PTR_ERR(inode);
184        down(&bi->wd.lock);
185        err = fsop_create(bi, dir, dentry->d_name.name, mode, excl, inode);
186        up(&bi->wd.lock);
187        if (!err) {
188                insert_inode_hash(inode);
189                d_instantiate(dentry, inode);
190                return 0;
191        } else
192          bilbyfs_err("BilbyFsError: fsop_create() = %d\n", err);
193        make_bad_inode(inode);
194        iput(inode);
195        return err;
196}
197
198static int bilbyfs_unlink(struct inode *dir, struct dentry *dentry)
199{
200        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
201        int err;
202
203        down(&bi->wd.lock);
204        err = fsop_unlink(bi, dir, dentry->d_name.name, dentry->d_inode);
205        up(&bi->wd.lock);
206        if (err)
207          bilbyfs_err("BilbyFsError: fsop_unlink() = %d\n", err);
208        return err;
209}
210
211static int bilbyfs_rmdir(struct inode *dir, struct dentry *dentry)
212{
213        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
214        int err;
215
216        down(&bi->wd.lock);
217        err = fsop_rmdir(bi, dir, dentry->d_name.name, dentry->d_inode);
218        up(&bi->wd.lock);
219        if (err)
220          bilbyfs_err("BilbyFsError: fsop_rmdir() = %d\n", err);
221
222        return err;
223}
224
225static int bilbyfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
226{
227        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
228        struct inode *inode;
229        int err;
230
231        bilbyfs_debug("bilbyfs_mkdir (dir.ino = %lu, name=%.*s, mode=%x)\n", dir->i_ino, dentry->d_name.len, dentry->d_name.name, mode);
232        inode = bilbyfs_new_inode(dir->i_sb, dir, S_IFDIR | mode);
233        if (IS_ERR(inode))
234                return PTR_ERR(inode);
235        down(&bi->wd.lock);
236        err = fsop_mkdir(bi, dir, dentry->d_name.name, mode, inode);
237        up(&bi->wd.lock);
238        if (!err) {
239                insert_inode_hash(inode);
240                d_instantiate(dentry, inode);
241                return 0;
242        } else
243          bilbyfs_err("BilbyFsError: bilbyfs_mkdir() = %d\n", err);
244        make_bad_inode(inode);
245        iput(inode);
246        return err;
247}
248
249static int bilbyfs_readdir(struct file *file, struct dir_context *ctx)
250{
251        struct dentry *dentry = file->f_path.dentry;
252        struct inode *dir = dentry->d_inode;
253        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
254        int err;
255
256        bilbyfs_debug("bilbyfs_readdir (dir.ino = %lu, name=%.*s, pos=%lld)\n",
257                        dir->i_ino, dentry->d_name.len, dentry->d_name.name, ctx->pos);
258        if (ctx->pos == 2) /* pos == 2 means an error occured */
259                return 0;
260        if (ctx->pos < 2) {
261                if (!dir_emit_dots(file, ctx))
262                        return 0;
263                ctx->pos = 3;
264        }
265        down(&bi->wd.lock);
266        err = fsop_readdir(bi, dir, ctx, (struct fsop_readdir_ctx **) &file->private_data);
267        up(&bi->wd.lock);
268        if (err) {
269                bilbyfs_err("BilbyFsError: bilbyfs_readdir() = %d\n", err);
270                ctx->pos = 2;
271                return err;
272        }
273        return 0;
274}
275
276static int bilbyfs_dir_release(struct inode *dir, struct file *file)
277{
278        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
279        bilbyfs_debug("bilbyfs_dir_release()\n");
280        down(&bi->wd.lock);
281        fsop_dir_release((struct fsop_readdir_ctx *)file->private_data);
282        up(&bi->wd.lock);
283        file->private_data = NULL;
284        return 0;
285}
286
287static loff_t bilbyfs_dir_llseek(struct file *file, loff_t offset, int origin)
288{
289        struct inode *inode = file->f_path.dentry->d_inode;
290        struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
291        int err;
292        /* When a directory is seeked 2 thing:
293         * - The current bri becomes useless
294         * - Seeking a directory is moronic, we do not support
295         * FIXME: Check whether not supporting is acceptable
296         * The alternative is to ignore, worst case hack something
297         * around to emulate.
298         */
299        bilbyfs_err("Warning: bilbyfs_dir_llseek(), this function is deprecated!");
300        down(&bi->wd.lock);
301        err = bilbyfs_dir_release(inode, file);
302        up(&bi->wd.lock);
303        return err;
304}
305
306static int bilbyfs_symlink(struct inode *dir, struct dentry *dentry,
307                    const char *symname)
308{
309        struct bilbyfs_info *bi = dir->i_sb->s_fs_info;
310        struct inode *inode;
311        int err;
312
313        bilbyfs_debug("bilbyfs_symlink (dir.ino = %lu, name=%.*s, symname=%s)\n", dir->i_ino, dentry->d_name.len, dentry->d_name.name, symname);
314        inode = bilbyfs_new_inode(dir->i_sb, dir, S_IFLNK | S_IRWXUGO);
315        if (IS_ERR(inode))
316                return PTR_ERR(inode);
317        down(&bi->wd.lock);
318        err = fsop_symlink(bi, dir, dentry->d_name.name, symname, inode);
319        up(&bi->wd.lock);
320        if (!err) {
321                insert_inode_hash(inode);
322                d_instantiate(dentry, inode);
323                return 0;
324        }
325	bilbyfs_err("BilbyFsError: bilbyfs_symlink() = %d\n", err);
326        make_bad_inode(inode);
327        iput(inode);
328        return err;
329}
330
331static int bilbyfs_rename(struct inode *old_dir, struct dentry *old_dentry,
332                          struct inode *new_dir, struct dentry *new_dentry
333#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
334                          , unsigned int flags
335#endif
336    )
337{
338        struct bilbyfs_info *bi = old_dir->i_sb->s_fs_info;
339        int err;
340
341#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,8,0)
342	if (flags & ~RENAME_NOREPLACE)
343		return -EINVAL;
344#endif
345        down(&bi->wd.lock);
346        err = fsop_rename(bi, old_dir, old_dentry->d_name.name,
347                          old_dentry->d_inode, new_dir, new_dentry->d_name.name,
348                          new_dentry->d_inode);
349        up(&bi->wd.lock);
350        if (err)
351          bilbyfs_err("BilbyFsError: bilbyfs_rename() = %d\n", err);
352        return err;
353}
354
355static int bilbyfs_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
356{
357        struct inode *inode = filp->f_mapping->host;
358        struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
359        int err;
360
361        err = filemap_write_and_wait_range(inode->i_mapping, start, end);
362        if (!err) {
363                down(&bi->wd.lock);
364                err = fsop_sync_fs(bi, inode->i_sb, 1);
365                up(&bi->wd.lock);
366                if (err)
367                        bilbyfs_err("BilbyFsError: bilbyfs_fsync() = %d\n", err);
368        } else {
369                bilbyfs_err("BilbyFsError: filemap_and_wait_range() = %d\n", err);
370        }
371        return err;
372}
373
374static int bilbyfs_readpage(struct file *filp, struct page *page)
375{
376        struct inode *inode = page->mapping->host;
377        struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
378        void *addr;
379        int err;
380
381        bilbyfs_debug("[0] bilbyfs_readpage(page = %p)\n", page);
382        addr = kmap(page);
383        down(&bi->wd.lock);
384        err = fsop_readpage(bi, inode, page->index, addr);
385        up(&bi->wd.lock);
386        if (err == -ENOENT) {
387                 SetPageChecked(page);
388                 err = 0;
389        }
390        if (err) {
391                ClearPageUptodate(page);
392                SetPageError(page);
393                flush_dcache_page(page);
394                kunmap(page);
395                unlock_page(page);
396                bilbyfs_err("BilbyFsError: bilbyfs_readpage() = %d\n", err);
397                return err;
398        }
399        SetPageUptodate(page);
400        ClearPageError(page);
401        flush_dcache_page(page);
402        kunmap(page);
403        unlock_page(page);
404        bilbyfs_debug("[2] bilbyfs_readpage() = %d\n", 0);
405        return 0;
406}
407
408static int bilbyfs_write_begin(struct file *filp, struct address_space *mapping,
409                               loff_t pos, unsigned len, unsigned flags,
410                               struct page **pagep, void **fsdata)
411{
412        struct page *page;
413        struct inode *inode = mapping->host;
414        struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
415        pgoff_t block = pos >> BILBYFS_BLOCK_SHIFT;
416        void *addr;
417        int err = 0;
418
419        bilbyfs_debug("[0] bilbyfs_write_begin()\n");
420        page = grab_cache_page_write_begin(mapping, block, flags);
421        if (!page)
422                return -ENOMEM;
423
424        addr = kmap(page);
425
426        if (!PageUptodate(page)) { /* overwriting data */
427                /* FIXME: optimisation, check whether the entire page is gonna be
428                 * overwritten and set PageChecked accordingly
429                 */
430                down(&bi->wd.lock);
431                err = fsop_write_begin(bi, inode, pos, len, addr);
432                up(&bi->wd.lock);
433                if (err) {
434                        ClearPageUptodate(page);
435                        SetPageError(page);
436                        kunmap(page);
437                        unlock_page(page);
438                        put_page(page);
439                        bilbyfs_err("BilbyFsError: bilbyfs_write_begin() = %d\n", err);
440                        return err;
441                }
442        }
443        SetPageUptodate(page);
444        ClearPageError(page);
445        kunmap(page);
446        *pagep = page;
447        bilbyfs_debug("[2] bilbyfs_write_begin() = 0\n");
448        return 0;
449}
450
451static int bilbyfs_write_end(struct file *filp, struct address_space *mapping,
452                             loff_t pos, unsigned len, unsigned copied,
453                             struct page *page, void *fsdata)
454{
455        struct inode *inode = mapping->host;
456        struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
457        void *addr;
458        int err;
459
460        bilbyfs_debug("[S] bilbyfs_write_end()\n");
461        BUG_ON(!PageUptodate(page));
462        /* if len > PAGE_SIZE then some data hasn't been copied by
463         * bilbyfs
464         */
465        if (copied < len) {
466                /* Something went wrong VFS did not copy all data initially
467                 * announced in write_begin.
468                 * FIXME Is returning 0 really asking VFS to retry?
469                 * FIXME Or should we just write the provided data ?
470                 */
471                /* 23/10/2013: This can safely be ignored because BilbyFs
472                 * always read a PAGE_SIZE data block in write_begin
473                 * which means that as long as @len is < PAGE_SIZE
474                 * we have read enough data.
475                 * FIXME: Can this ever happen without concurrency?
476                 */
477                bilbyfs_debug("copied < len : %u < %u. But it's safe to ignore as write_begin read %lu bytes.\n",
478                              copied, len, PAGE_SIZE);
479                /* return 0; */
480        }
481        addr = kmap(page);
482        down(&bi->wd.lock);
483        err = fsop_write_end(bi, inode, pos, copied, addr);
484        up(&bi->wd.lock);
485        if (!err) {
486                kunmap(page);
487                unlock_page(page);
488                put_page(page);
489                bilbyfs_debug("[1] bilbyfs_write_end() = %d\n", copied);
490                return copied;
491        }
492        SetPageError(page);
493        kunmap(page);
494        unlock_page(page);
495        put_page(page);
496        bilbyfs_err("BilbyFsError: bilbyfs_write_end() = %d\n", err);
497        return err;
498}
499
500static int bilbyfs_write_end_writeback(struct file *filp, struct address_space *mapping,
501                                       loff_t pos, unsigned len, unsigned copied,
502                                       struct page *page, void *fsdata)
503{
504        struct inode *inode = mapping->host;
505        loff_t end_pos = pos + len;
506        int appending = !!(end_pos > inode->i_size);
507
508        bilbyfs_assert(PAGE_SIZE == BILBYFS_BLOCK_SIZE);
509        bilbyfs_debug("[S] bilbyfs_write_end_writeback(pos = %llu, len =%u, copied = %u)\n",pos, len, copied);
510        BUG_ON(!PageUptodate(page));
511        bilbyfs_assert(len <= PAGE_SIZE);
512        if (copied < len) {
513                /* 23/10/2013: This can safely be ignored because BilbyFs
514                 * always read a PAGE_SIZE data block in write_begin
515                 * which means that as long as @len is < PAGE_SIZE
516                 * we have read enough data.
517                 * FIXME: Can this ever happen without concurrency?
518                 */
519                bilbyfs_debug("copied < len : %u < %u. But it's safe to ignore as write_begin read %lu bytes.\n",
520                              copied, len, PAGE_SIZE);
521        }
522        __set_page_dirty_nobuffers(page);
523        if (appending) {
524                i_size_write(inode, end_pos);
525                /*
526                 * Note, we do not set @I_DIRTY_PAGES (which means that the
527                 * inode has dirty pages), this has been done in
528                 * '__set_page_dirty_nobuffers()'.
529                 */
530                __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
531        }
532        unlock_page(page);
533        put_page(page);
534        bilbyfs_debug("[1] bilbyfs_write_end_writeback() = %d (nb bytes copied)\n", copied);
535        return copied;
536}
537
538static int bilbyfs_writepage(struct page *page, struct writeback_control *wbc)
539{
540        struct inode *inode = page->mapping->host;
541        struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
542        loff_t i_size =  i_size_read(inode);
543        pgoff_t end_index = i_size >> PAGE_SHIFT;
544        loff_t pos = page->index << PAGE_SHIFT;
545        int err, len = i_size & (PAGE_SIZE - 1);
546        void *kaddr;
547
548        bilbyfs_debug("bilbyfs_writepage()\n");
549
550        /* Is the page fully outside @i_size? (truncate in progress) */
551        if (page->index > end_index || (page->index == end_index && !len)) {
552                unlock_page(page);
553                return 0;
554        }
555        bilbyfs_debug("write-to-disk\n");
556        if (page->index != end_index)
557                len = PAGE_SIZE;
558        set_page_writeback(page);
559        kaddr = kmap_atomic(page);
560        memset(kaddr + len, 0, PAGE_SIZE - len);
561        flush_dcache_page(page);
562        kunmap_atomic(kaddr);
563
564        kaddr = kmap(page);
565        down(&bi->wd.lock);
566        err = fsop_write_end(bi, inode, pos, len, kaddr);
567        up(&bi->wd.lock);
568        kunmap(page);
569        unlock_page(page);
570        end_page_writeback(page);
571
572        if (err)
573                bilbyfs_err("BilbyFsError: bilbyfs_writepage() = %d\n", err);
574        return err;
575}
576
577#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
578static void *bilbyfs_follow_link(struct dentry *dentry, struct nameidata *nd)
579{
580        struct bilbyfs_info *bi = dentry->d_inode->i_sb->s_fs_info;
581        struct inode *inode = dentry->d_inode;
582        int err;
583
584        bilbyfs_debug("bilbyfs_follow_link() \n");
585        if (!inode->i_private) {
586                inode->i_private = kmalloc(PATH_MAX);
587                if (!inode->i_private)
588                        return ERR_PTR(-ENOMEM);
589
590                down(&bi->wd.lock);
591                err = fsop_follow_link(bi, dentry->d_inode, inode->i_private);
592                up(&bi->wd.lock);
593                if (err) {
594                        bilbyfs_err("BilbyFsError: bilbyfs_follow_link() = %d\n", err);
595                        kfree(inode->i_private);
596                        return ERR_PTR(err);
597                }
598
599        }
600#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
601        nd_set_link(nd, inode->i_private);
602#endif
603        return NULL;
604}
605#else
606const char *bilbyfs_get_link(struct dentry *dentry, struct inode *inode,
607                             struct delayed_call *done)
608{
609        struct bilbyfs_info *bi = dentry->d_inode->i_sb->s_fs_info;
610	int err;
611
612	if (!inode->i_link) {
613		inode->i_link = kmalloc(PATH_MAX);
614		if (!inode->i_link)
615			return ERR_PTR(-ENOMEM);
616		down(&bi->wd.lock);
617		err = fsop_follow_link(bi, dentry->d_inode, inode->i_link);
618		up(&bi->wd.lock);
619
620		if (err) {
621			bilbyfs_err("BilbyFsError: bilbyfs_follow_link() = %d\n", err);
622			kfree(inode->i_link);
623			inode->i_link = NULL;
624			return ERR_PTR(err);
625		}
626	}
627	return inode->i_link;
628}
629#endif
630
631static int bilbyfs_setattr(struct dentry *dentry, struct iattr *attr)
632{
633        struct inode *inode = dentry->d_inode;
634        struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
635        int err;
636
637        bilbyfs_debug("bilbyfs_setattr(ino %lu, mode %#x, ia_valid %#x)\n",
638                inode->i_ino, inode->i_mode, attr->ia_valid);
639#if LINUX_VERSION_CODE > KERNEL_VERSION(4,9,0)
640        err = setattr_prepare(dentry, attr);
641#else
642        err = inode_change_ok(inode, attr);
643#endif
644
645        if (err)
646                return err;
647
648        if (attr->ia_valid & ATTR_MODE) {
649                if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
650                        attr->ia_mode &= ~S_ISGID;
651        }
652
653        down(&bi->wd.lock);
654        err = fsop_setattr(bi, inode, attr);
655        up(&bi->wd.lock);
656        if (err) {
657                bilbyfs_err("BilbyFsError: fsop_setattr() = %d\n", err);
658                return err;
659        }
660        /* truncate_setsize calls i_size_write and frees pages in the
661         * page cache */
662        if (attr->ia_valid & ATTR_SIZE)
663                truncate_setsize(inode, inode->i_size);
664        if (attr->ia_valid & ATTR_ATIME)
665                inode->i_atime = timespec64_trunc(inode->i_atime,
666                                                inode->i_sb->s_time_gran);
667        if (attr->ia_valid & ATTR_MTIME)
668                inode->i_mtime = timespec64_trunc(inode->i_mtime,
669                                                inode->i_sb->s_time_gran);
670        if (attr->ia_valid & ATTR_CTIME)
671                inode->i_ctime = timespec64_trunc(inode->i_ctime,
672                                                inode->i_sb->s_time_gran);
673        return 0;
674}
675
676
677#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
678static int bilbyfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
679                           struct kstat *stat)
680{
681       struct inode *inode = dentry->d_inode;
682       struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
683       int err;
684
685       down(&bi->wd.lock);
686       err = fsop_getattr(bi, inode, stat);
687       up(&bi->wd.lock);
688       if (!err) {
689               stat->dev = dentry->d_sb->s_dev;
690               stat->rdev = inode->i_rdev;
691       } else {
692               bilbyfs_err("BilbyFsError: fsop_getattr = %d", err);
693       }
694       return err;
695}
696#else
697int bilbyfs_getattr(const struct path *path, struct kstat *stat,
698                    u32 mask, unsigned int flags)
699{
700       struct dentry *dentry = path->dentry;
701       struct inode *inode = d_inode(dentry);
702       int err;
703       struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
704
705       down(&bi->wd.lock);
706       err = fsop_getattr(bi, inode, stat);
707       up(&bi->wd.lock);
708
709       if (!err) {
710               stat->dev = dentry->d_sb->s_dev;
711               stat->rdev = inode->i_rdev;
712       } else {
713               bilbyfs_err("BilbyFsError: fsop_getattr = %d", err);
714       }
715       return err;
716}
717#endif
718
719const struct file_operations bilbyfs_file_operations =
720{
721        .llseek =       generic_file_llseek,
722        .open =         generic_file_open,
723#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
724        .read =         new_sync_read,
725        .write =        new_sync_write,
726#endif
727        .read_iter =    generic_file_read_iter,
728        .write_iter =   generic_file_write_iter,
729        .mmap =         generic_file_readonly_mmap,
730        .fsync =        bilbyfs_fsync,
731        .splice_read =  generic_file_splice_read,
732};
733
734const struct inode_operations bilby_file_inode_operations =
735{
736        .setattr =      bilbyfs_setattr,
737};
738
739const struct inode_operations bilbyfs_symlink_inode_operations = {
740#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
741        .readlink    = generic_readlink,
742        .follow_link = bilbyfs_follow_link,
743#else
744        .get_link = bilbyfs_get_link,
745#endif
746        .setattr     = bilbyfs_setattr,
747        .getattr     = bilbyfs_getattr,
748};
749
750
751const struct inode_operations bilbyfs_file_inode_operations = {
752        .setattr     = bilbyfs_setattr,
753        .getattr     = bilbyfs_getattr,
754};
755
756const struct inode_operations bilbyfs_dir_inode_operations = {
757        .lookup      = bilbyfs_lookup,
758        .create      = bilbyfs_create,
759        .link        = bilbyfs_link,
760        .symlink     = bilbyfs_symlink,
761        .unlink      = bilbyfs_unlink,
762        .mkdir       = bilbyfs_mkdir,
763        .rmdir       = bilbyfs_rmdir,
764        .rename      = bilbyfs_rename,
765        .setattr     = bilbyfs_setattr,
766/*
767        .mknod       = bilbyfs_mknod,
768*/
769        .getattr     = bilbyfs_getattr,
770};
771
772const struct file_operations bilbyfs_dir_operations = {
773        .llseek         = bilbyfs_dir_llseek,
774        .release        = bilbyfs_dir_release,
775        .fsync          = bilbyfs_fsync,
776        .read           = generic_read_dir,
777        .iterate        = bilbyfs_readdir,
778};
779
780const struct address_space_operations bilbyfs_file_address_operations =
781{
782        .readpage =     bilbyfs_readpage,
783        .write_begin =  bilbyfs_write_begin,
784#ifdef NOWRITEBACK
785        .write_end =    bilbyfs_write_end,
786#else
787        .writepage  =   bilbyfs_writepage,
788        .write_end  =   bilbyfs_write_end_writeback,
789#endif
790};
791
792static int bilbyfs_statfs(struct dentry *dentry, struct kstatfs *kstat)
793{
794        struct bilbyfs_info *bi = dentry->d_inode->i_sb->s_fs_info;
795        int err;
796
797        down(&bi->wd.lock);
798        err = fsop_statfs(bi, kstat);
799        up(&bi->wd.lock);
800        return err;
801}
802
803static int bilbyfs_sync_fs(struct super_block *sb, int wait)
804{
805        struct bilbyfs_info *bi = sb->s_fs_info;
806        int err;
807
808        down(&bi->wd.lock);
809        err = fsop_sync_fs(bi, sb, wait);
810        up(&bi->wd.lock);
811        if (err)
812          bilbyfs_err("BilbyFsError: bilbyfs_link() = %d\n", err);
813        return err;
814}
815
816/**
817 * bilbyfs_unmount - unmount BilbyFs
818 * @bi: global fs info
819 *
820 */
821static void bilbyfs_unmount(struct bilbyfs_info *bi)
822{
823        bilbyfs_debug("bilbyfs_unmount()\n");
824        down(&bi->wd.lock);
825        fsop_unmount(bi);
826        up(&bi->wd.lock);
827}
828
829static void bilbyfs_put_super(struct super_block *sb)
830{
831        struct bilbyfs_info *bi = sb->s_fs_info;
832
833        bilbyfs_msg("unmount UBI device %d, volume %d", bi->vi.ubi_num,
834                  bi->vi.vol_id);
835
836        bilbyfs_debug("bilbyfs_put_super()\n");
837        bilbyfs_unmount(bi);
838#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
839        bdi_destroy(sb->s_bdi);
840#endif
841        ubi_close_volume(bi->ubi); /* FIXME: This should be in umount */
842}
843
844/**
845 * open_ubi - parse UBI device name string and open the UBI device.
846 * @name: UBI volume name
847 * @mode: UBI volume open mode
848 *
849 * The primary method of mounting BilbyFs is by specifying the UBI volume
850 * character device node path. However, BilbyFs may also be mounted withoug any
851 * character device node using one of the following methods:
852 *
853 * o ubiX_Y    - mount UBI device number X, volume Y;
854 * o ubiY      - mount UBI device number 0, volume Y;
855 * o ubiX:NAME - mount UBI device X, volume with name NAME;
856 * o ubi:NAME  - mount UBI device 0, volume with name NAME.
857 *
858 * Alternative '!' separator may be used instead of ':' (because some shells
859 * like busybox may interpret ':' as an NFS host name separator). This function
860 * returns UBI volume description object in case of success and a negative
861 * error code in case of failure.
862 */
863struct ubi_volume_desc *open_ubi(const char *name, int mode)
864{
865        struct ubi_volume_desc *ubi;
866        int dev, vol;
867        char *endptr;
868
869        /* First, try to open using the device node path method */
870        ubi = ubi_open_volume_path(name, mode);
871        if (!IS_ERR(ubi))
872                return ubi;
873
874        /* Try the "nodev" method */
875        if (name[0] != 'u' || name[1] != 'b' || name[2] != 'i')
876                return ERR_PTR(-EINVAL);
877
878        /* ubi:NAME method */
879        if ((name[3] == ':' || name[3] == '!') && name[4] != '\0')
880                return ubi_open_volume_nm(0, name + 4, mode);
881
882        if (!isdigit(name[3]))
883                return ERR_PTR(-EINVAL);
884
885        dev = simple_strtoul(name + 3, &endptr, 0);
886
887        /* ubiY method */
888        if (*endptr == '\0')
889                return ubi_open_volume(0, dev, mode);
890
891        /* ubiX_Y method */
892        if (*endptr == '_' && isdigit(endptr[1])) {
893                vol = simple_strtoul(endptr + 1, &endptr, 0);
894                if (*endptr != '\0')
895                        return ERR_PTR(-EINVAL);
896                return ubi_open_volume(dev, vol, mode);
897        }
898
899        /* ubiX:NAME method */
900        if ((*endptr == ':' || *endptr == '!') && endptr[1] != '\0')
901                return ubi_open_volume_nm(dev, ++endptr, mode);
902
903        return ERR_PTR(-EINVAL);
904}
905
906enum {
907        BilbyFs_Opt_no_summary,
908        BilbyFs_Opt_compr,
909        BilbyFs_Opt_end,
910};
911
912static const match_table_t bilbyfs_options = {
913        {BilbyFs_Opt_no_summary, "no_summary"},
914        {BilbyFs_Opt_compr, "compr=%s"},
915        {BilbyFs_Opt_end, NULL},
916};
917
918static int bilbyfs_parse_options(struct bilbyfs_info *bi, char *options)
919{
920        char *s;
921        substring_t args[MAX_OPT_ARGS];
922
923        if (!options)
924                return 0;
925
926        while ((s = strsep(&options, ",")) && *s) {
927                int opt;
928
929                opt = match_token(s, bilbyfs_options, args);
930                switch (opt) {
931                case BilbyFs_Opt_no_summary:
932                        bi->no_summary = 1;
933                        bilbyfs_err("BilbyFs option: no_summary\n");
934                        break;
935                case BilbyFs_Opt_compr:
936                        bilbyfs_err("BilbyFs option: compr=%%s ignored (No compression)\n");
937                        break;
938                default:
939                {
940                        bilbyfs_err("unreconized mount option \"%s\"\n", s);
941                        return -EINVAL;
942                }
943                }
944        }
945        return 0;
946}
947
948
949static int bilbyfs_fill_super(struct super_block *sb, void *options, int silent, char *bd_name)
950{
951        struct bilbyfs_info *bi = sb->s_fs_info;
952        struct inode *root;
953        int err;
954        ino_t rootino;
955
956        err = bilbyfs_parse_options(bi, options);
957        if (err)
958                return err;
959        /*
960         * Disabling VFS's read-ahead feature.
961         * Read-ahead will be disabled because bdi->ra_pages is 0.
962         */
963#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
964
965        sb->s_bdi = &bi->wd.bdi;
966        sb->s_bdi->name = "bilbyfs";
967        sb->s_bdi->capabilities = BDI_CAP_MAP_COPY;
968        err = bdi_init(sb->s_bdi);
969        if (!err) {
970                err = bdi_register(sb->s_bdi, NULL, bd_name);
971                if (!err) {
972                        sb->s_fs_info = bi;
973                        root = bilbyfs_new_inode(sb, NULL, S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO);
974                        if (root) {
975                                set_nlink(root, 2);
976                                down(&bi->wd.lock);
977                                err = fsop_fill_super(bi, sb, silent, &rootino, root);
978                                up(&bi->wd.lock);
979                                iput(root);
980                        } else {
981                                err = PTR_ERR(root);
982                        }
983
984                        if (!err) {
985                                /* Reads the root inode */
986                                root = bilbyfs_iget(bi, rootino);
987                                if (!IS_ERR(root)) {
988                                        sb->s_root = d_make_root(root);
989                                        if (sb->s_root)
990                                                return 0;
991                                        err = -EINVAL;
992                                } else {
993                                        err = PTR_ERR(root);
994                                }
995                                bilbyfs_unmount(bi);
996                        }
997                        bdi_destroy(sb->s_bdi);
998                }
999        }
1000#else
1001        super_setup_bdi(sb);
1002	//        sb->s_fs_info = wd;
1003        root = bilbyfs_new_inode(sb, NULL, S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO);
1004        if (root) {
1005                set_nlink(root, 2);
1006                err = fsop_fill_super(bi, sb, silent, &rootino, root);
1007                iput(root);
1008        } else {
1009                err = PTR_ERR(root);
1010        }
1011
1012        if (!err) {
1013                /* Reads the root inode */
1014                root = bilbyfs_iget(bi, root->i_ino);
1015                if (!IS_ERR(root)) {
1016                        sb->s_root = d_make_root(root);
1017                        if (sb->s_root)
1018                                return 0;
1019                        err = -EINVAL;
1020                } else {
1021                        err = PTR_ERR(root);
1022                }
1023                bilbyfs_unmount(bi);
1024        }
1025#endif
1026        sb->s_bdi = NULL;
1027        return err;
1028}
1029
1030static int sb_test(struct super_block *sb, void *data)
1031{
1032        struct bilbyfs_info *bi = sb->s_fs_info;
1033        int err;
1034
1035        down(&bi->wd.lock);
1036        err = fsop_test_is_mount(data, bi);
1037        up(&bi->wd.lock);
1038        return err;
1039}
1040
1041static int sb_set(struct super_block *sb, void *data)
1042{
1043        sb->s_fs_info = data;
1044        return set_anon_super(sb, NULL);
1045}
1046
1047static const struct super_operations bilbyfs_super_operations;
1048
1049/**
1050 * bilbyfs_mount: mount the file system
1051 * @fs_type: Linux file system type reference
1052 * @flags: MS_* flags (MS_RDONLY, MS_NOATIME, ...)
1053 * @name: name of the ubi volume to mount
1054 * @data: private pointer to store some fs specific data
1055 */
1056struct dentry *bilbyfs_mount(struct file_system_type *fs_type, int flags,
1057                             const char *name, void *data)
1058{
1059        struct bilbyfs_info *bi;
1060        struct super_block *sb;
1061        char bd_name[BILBYFS_BD_MAX_NLEN];
1062        int err;
1063
1064        bilbyfs_err("Mounting BilbyFs %s, flags %#x\n", name, flags);
1065        bi = kzalloc(sizeof(struct bilbyfs_info));
1066        if (bi) {
1067                wrapper_init(&bi->wd);
1068                down(&bi->wd.lock);
1069                err = fsop_init(bi, name, bd_name);
1070                up(&bi->wd.lock);
1071                if (!err) {
1072                        sb = sget(fs_type, sb_test, sb_set, flags, bi);
1073                        if (!IS_ERR(sb)) {
1074                                /* 'fill_super()' opens ubi again so we must close it here */
1075                                if (sb->s_root) {
1076                                        kfree(bi);
1077                                        /* A new mount point for already mounted BilbyFs */
1078                                        return dget(sb->s_root);
1079                                } else {
1080                                        sb->s_flags = flags;
1081                                        sb->s_op = &bilbyfs_super_operations;
1082                                        err = bilbyfs_fill_super(sb, data,
1083                                                !!(flags & MS_SILENT), bd_name);
1084                                        if (!err) {
1085                                                /* We do not support atime */
1086                                                sb->s_flags |= MS_ACTIVE | MS_NOATIME;
1087                                                bilbyfs_debug("bilbyfs_mount() = %d\n", err);
1088                                                return dget(sb->s_root);
1089                                        }
1090                                        deactivate_locked_super(sb);
1091                                }
1092                        } else {
1093                                err = PTR_ERR(sb);
1094                                kfree(bi);
1095                        }
1096                }
1097        } else {
1098                err = -ENOMEM;
1099        }
1100        bilbyfs_debug("bilbyfs_mount() = %d\n", err);
1101        return ERR_PTR(err);
1102}
1103
1104/**
1105 * bilbyfs_kill_super: free linux super block instance.
1106 * @sb: Linux super block reference
1107 */
1108void bilbyfs_kill_super(struct super_block *sb)
1109{
1110        struct bilbyfs_info *bi = sb->s_fs_info;
1111
1112        bilbyfs_debug("bilbyfs_kill_super()\n");
1113        kill_anon_super(sb);
1114        down(&bi->wd.lock);
1115        fsop_clean(bi);
1116        up(&bi->wd.lock);
1117        kfree(bi);
1118}
1119
1120struct kmem_cache *bilbyfs_inode_slab;
1121
1122static struct inode *bilbyfs_alloc_inode(struct super_block *sb)
1123{
1124        struct bilbyfs_inode *binode;
1125
1126        binode = kmem_cache_alloc(bilbyfs_inode_slab, GFP_NOFS);
1127        if (!binode)
1128                return NULL;
1129
1130        memset((void *)binode + sizeof(struct inode), 0,
1131               sizeof(struct bilbyfs_inode) - sizeof(struct inode));
1132        return &binode->vfs_inode;
1133}
1134
1135static void bilbyfs_free_inode(struct rcu_head *head)
1136{
1137        struct inode *inode = container_of(head, struct inode, i_rcu);
1138        struct bilbyfs_inode *binode = inode_to_binode(inode);
1139
1140        bilbyfs_debug("bilbyfs_free_inode(ino = %lu)\n", inode->i_ino);
1141
1142	kfree(inode->i_link);
1143        kmem_cache_free(bilbyfs_inode_slab, binode);
1144}
1145
1146static void bilbyfs_destroy_inode(struct inode *inode)
1147{
1148        bilbyfs_debug("bilbyfs_destroy_inode(ino=%lu)\n", inode->i_ino);
1149	kfree(inode->i_private);
1150	inode->i_private = NULL;
1151
1152        call_rcu(&inode->i_rcu, bilbyfs_free_inode);
1153}
1154
1155static void bilbyfs_evict_inode(struct inode *inode)
1156{
1157        struct bilbyfs_info *bi = inode->i_sb->s_fs_info;
1158
1159        bilbyfs_debug("bilbyfs_evict_inode(ino = %lu)\n", inode->i_ino);
1160        bilbyfs_assert(!atomic_read(&inode->i_count));
1161
1162        truncate_inode_pages(&inode->i_data, 0);
1163        if (!is_bad_inode(inode)) {
1164                down(&bi->wd.lock);
1165                fsop_evict_inode(bi, inode);
1166                up(&bi->wd.lock);
1167        }
1168        clear_inode(inode);
1169}
1170
1171struct timespec64 inode_current_time(struct inode *inode)
1172{
1173  return current_time(inode);
1174}
1175
1176static const struct super_operations bilbyfs_super_operations =
1177{
1178        .alloc_inode    = bilbyfs_alloc_inode,
1179        .destroy_inode  = bilbyfs_destroy_inode,
1180        .put_super      = bilbyfs_put_super,
1181        .statfs         = bilbyfs_statfs,
1182        /* .remount_fs     = bilbyfs_remount_fs, */
1183        .evict_inode    = bilbyfs_evict_inode,
1184        .sync_fs        = bilbyfs_sync_fs,
1185};
1186
1187static struct file_system_type bilbyfs_fs_type = {
1188        .name    = "bilbyfs",
1189        .owner   = THIS_MODULE,
1190        .mount   = bilbyfs_mount,
1191        .kill_sb = bilbyfs_kill_super,
1192};
1193
1194/*
1195 * Inode slab cache constructor.
1196 */
1197static void inode_slab_ctor(void *obj)
1198{
1199        struct bilbyfs_inode *bi = obj;
1200        inode_init_once(&bi->vfs_inode);
1201}
1202
1203static int __init bilbyfs_init(void)
1204{
1205        int err;
1206
1207        /* Make sure node sizes are 8-byte aligned (BILBYFS_OBJ_PADDING) */
1208        BUILD_BUG_ON((BILBYFS_OBJ_PADDING - 1) != 7);
1209        BUILD_BUG_ON(BILBYFS_CH_SZ      & 7);
1210        BUILD_BUG_ON(BILBYFS_INODE_SZ   & 7);
1211        BUILD_BUG_ON(BILBYFS_DENTARR_SZ & 7);
1212        BUILD_BUG_ON(BILBYFS_DATA_SZ    & 7);
1213        BUILD_BUG_ON(BILBYFS_DATA_SZ    & 7);
1214        BUILD_BUG_ON(BILBYFS_MAX_DATA_SZ & 7);
1215        BUILD_BUG_ON(BILBYFS_MAX_DENTARR_SZ & 7);
1216        BUILD_BUG_ON(BILBYFS_SUPER_SZ    & 7);
1217
1218        BUILD_BUG_ON(BILBYFS_FIRST_SQNUM <= 0);
1219        BUILD_BUG_ON(BILBYFS_FIRST_INO <= 0);
1220        BUILD_BUG_ON(BILBYFS_ROOT_INO >= BILBYFS_FIRST_INO);
1221
1222        /* Ensuring SUP_LNUM < LOG_FST_LNUM */
1223        BUILD_BUG_ON(BILBYFS_SUP_LNUM >= BILBYFS_LOG_FST_LNUM);
1224
1225        /* All obj types fit in 3 bits */
1226        BUILD_BUG_ON(BILBYFS_OBJ_TYPES_CNT > 7);
1227
1228        BUILD_BUG_ON(PAGE_SIZE != BILBYFS_BLOCK_SIZE);
1229        BUILD_BUG_ON(PAGE_SHIFT != BILBYFS_BLOCK_SHIFT);
1230
1231        bilbyfs_inode_slab = kmem_cache_create("bilbyfs_inode_slab",
1232                                sizeof(struct bilbyfs_inode), 0,
1233                                SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT,
1234                                &inode_slab_ctor);
1235        if (!bilbyfs_inode_slab)
1236                return -ENOMEM;
1237
1238        err = register_filesystem(&bilbyfs_fs_type);
1239        if (err) {
1240                bilbyfs_err("cannot register file system, error %d", err);
1241                kmem_cache_destroy(bilbyfs_inode_slab);
1242                return err;
1243        }
1244        return 0;
1245}
1246module_init(bilbyfs_init);
1247
1248static void __exit bilbyfs_exit(void)
1249{
1250        /* Not sure why UBIFS destroy the slab before unregistering
1251         * but for now we do the same. FIXME More investigation required.
1252         */
1253        rcu_barrier();
1254        kmem_cache_destroy(bilbyfs_inode_slab);
1255        unregister_filesystem(&bilbyfs_fs_type);
1256}
1257module_exit(bilbyfs_exit);
1258
1259MODULE_LICENSE("GPL");
1260MODULE_VERSION(__stringify(BILBYFS_VERSION));
1261MODULE_AUTHOR("Sidney Amani");
1262MODULE_DESCRIPTION("BilbyFs - Bilby File System");
1263
1264