struct qstr this;
        struct path path;
        struct file *file;
+       fmode_t mode;
        int error;
 
        if (IS_ERR(anon_inode_inode))
                return ERR_PTR(-ENODEV);
 
+       switch (flags & O_ACCMODE) {
+       case O_RDONLY: mode = FMODE_READ;               break;
+       case O_WRONLY: mode = FMODE_WRITE;              break;
+       case O_RDWR:   mode = FMODE_READ | FMODE_WRITE; break;
+       default:       return ERR_PTR(-EINVAL);
+       }
+
        if (fops->owner && !try_module_get(fops->owner))
                return ERR_PTR(-ENOENT);
 
        d_instantiate(path.dentry, anon_inode_inode);
 
        error = -ENFILE;
-       file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops);
+       file = alloc_file(&path, mode, fops);
        if (!file)
                goto err_dput;
        file->f_mapping = anon_inode_inode->i_mapping;
 
        file->f_pos = 0;
-       file->f_flags = O_RDWR | (flags & O_NONBLOCK);
+       file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
        file->f_version = 0;
        file->private_data = priv;
 
 
        ctx->flags = flags;
 
        file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx,
-                                 flags & EFD_SHARED_FCNTL_FLAGS);
+                                 O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS));
        if (IS_ERR(file))
                eventfd_free_ctx(ctx);
 
 
         * a file structure and a free file descriptor.
         */
        error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
-                                flags & O_CLOEXEC);
+                                O_RDWR | (flags & O_CLOEXEC));
        if (error < 0)
                ep_free(ep);
 
 
                 * anon_inode_getfd() will install the fd.
                 */
                ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx,
-                                      flags & (O_CLOEXEC | O_NONBLOCK));
+                                      O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK)));
                if (ufd < 0)
                        kfree(ctx);
        } else {
 
        hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
 
        ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
-                              flags & TFD_SHARED_FCNTL_FLAGS);
+                              O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS));
        if (ufd < 0)
                kfree(ctx);
 
 
        if (IS_ERR(event))
                goto err_put_context;
 
-       err = anon_inode_getfd("[perf_event]", &perf_fops, event, 0);
+       err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR);
        if (err < 0)
                goto err_free_put_context;
 
 
  */
 static int create_vcpu_fd(struct kvm_vcpu *vcpu)
 {
-       return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0);
+       return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, O_RDWR);
 }
 
 /*
        kvm = kvm_create_vm();
        if (IS_ERR(kvm))
                return PTR_ERR(kvm);
-       fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0);
+       fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR);
        if (fd < 0)
                kvm_put_kvm(kvm);