void pin_insert_group(struct fs_pin *pin, struct vfsmount *m, struct hlist_head *p) { spin_lock(&pin_lock); if (p) hlist_add_head(&pin->s_list, p); hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins); spin_unlock(&pin_lock); }
struct vfsmount* getParent(struct vfsmount* mnt) { #ifndef TALPA_REPLACE_MOUNT_STRUCT return mnt->mnt_parent; #else talpa_mount_struct *realmnt = real_mount(mnt); return &(realmnt->mnt_parent->mnt); #endif }
static int seq_show(struct seq_file *m, void *v) { struct files_struct *files = NULL; int f_flags = 0, ret = -ENOENT; struct file *file = NULL; struct task_struct *task; task = get_proc_task(m->private); if (!task) return -ENOENT; if (!gr_acl_handle_procpidmem(task)) files = get_files_struct(task); put_task_struct(task); if (files) { int fd = proc_fd(m->private); spin_lock(&files->file_lock); file = fcheck_files(files, fd); if (file) { struct fdtable *fdt = files_fdtable(files); f_flags = file->f_flags; if (close_on_exec(fd, fdt)) f_flags |= O_CLOEXEC; get_file(file); ret = 0; } spin_unlock(&files->file_lock); put_files_struct(files); } if (ret) return ret; seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n", (long long)file->f_pos, f_flags, real_mount(file->f_path.mnt)->mnt_id); show_fd_locks(m, file, files); if (seq_has_overflowed(m)) goto out; if (file->f_op->show_fdinfo) file->f_op->show_fdinfo(m, file); out: fput(file); return 0; }
/* mount our hidden southbound filesystem */ int ftfs_private_mount(const char *dev_name, const char *fs_type, void *data) { int err; struct vfsmount *vfs_mount; struct file_system_type *type; BUG_ON(ftfs_vfs); if (!dev_name || !*dev_name) { err = -EINVAL; goto err_out; } if (!fs_type || !*fs_type) { err = -EINVAL; goto err_out; } type = get_fs_type(fs_type); vfs_mount = vfs_kern_mount(type, FTFS_MS_FLAGS, dev_name, data); if (!IS_ERR(vfs_mount) && (type->fs_flags & FS_HAS_SUBTYPE) && !vfs_mount->mnt_sb->s_subtype) //mnt = ftfs_fs_set_subtype(mnt, fstype); BUG(); /* this causes problems during unmount. only for internal mounts */ //real_mount(vfs_mount)->mnt_ns = ERR_PTR(-EINVAL); ftfs_put_filesystem(type); if (IS_ERR(vfs_mount)) { err = PTR_ERR(vfs_mount); goto err_out; } mutex_lock(&ftfs_southbound_lock); ftfs_vfs = mntget(vfs_mount); mutex_unlock(&ftfs_southbound_lock); pr_devel("%s mnt_ns=%p\n", __func__, real_mount(vfs_mount)->mnt_ns); return 0; err_out: mutex_lock(&ftfs_southbound_lock); ftfs_vfs = NULL; mutex_unlock(&ftfs_southbound_lock); return err; }
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count) { struct file *file; ssize_t ret = -EBADF; int fput_needed; #ifdef CONFIG_DIRTY_SYSTEM_DETECTOR #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) struct mount *mnt; #else struct vfsmount *mnt; #endif #endif file = fget_light(fd, &fput_needed); #ifdef CONFIG_DIRTY_SYSTEM_DETECTOR if (!get_tamper_sf() && file != NULL) { if (board_mfg_mode() != 2 && strcmp("htcunzip", current->comm)) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) mnt = real_mount(file->f_path.mnt); #else mnt = file->f_path.mnt; #endif if (!strcmp("system", mnt->mnt_mountpoint->d_name.name)) { printk("%s to /system partition: file(%s)\n", __func__, file->f_path.dentry->d_name.name); mark_system_dirty(file->f_path.dentry->d_name.name); } } } #endif if (file) { loff_t pos = file_pos_read(file); ret = vfs_write(file, buf, count, &pos); file_pos_write(file, pos); fput_light(file, fput_needed); } return ret; }
static int get_absolute_path(unsigned char* buf, int buflen, struct file *filp) { unsigned char tmpstr[FILE_PATHLEN+FILE_NAMELEN]; struct dentry* tmpdentry = 0; struct mount* tmpmnt; struct mount* tmpoldmnt; tmpmnt = real_mount(filp->f_vfsmnt); tmpdentry = filp->f_path.dentry->d_parent; do { tmpoldmnt = tmpmnt; while (!IS_ROOT(tmpdentry)) { strcpy(tmpstr, buf); // // make codes robust strncpy(buf, tmpdentry->d_name.name, buflen - 1); buf[buflen - 1] = '\0'; if (strlen(buf) + strlen("/") > buflen -1) return -1; else strcat(buf, "/"); if (strlen(buf) + strlen(tmpstr) > buflen -1) return -1; else strcat(buf, tmpstr); tmpdentry = tmpdentry->d_parent; } tmpdentry = tmpmnt->mnt_mountpoint; tmpmnt = tmpmnt->mnt_parent; } while (tmpmnt != tmpoldmnt); strcpy(tmpstr, buf); strcpy(buf, "/"); // // make codes robust if (strlen(buf) + strlen(tmpstr) > buflen -1) return -1; strcat(buf, tmpstr); return 0; }
static long do_sys_name_to_handle(struct path *path, struct file_handle __user *ufh, int __user *mnt_id) { long retval; struct file_handle f_handle; int handle_dwords, handle_bytes; struct file_handle *handle = NULL; /* * We need to make sure whether the file system * support decoding of the file handle */ if (!path->dentry->d_sb->s_export_op || !path->dentry->d_sb->s_export_op->fh_to_dentry) return -EOPNOTSUPP; if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) return -EFAULT; if (f_handle.handle_bytes > MAX_HANDLE_SZ) return -EINVAL; handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes, GFP_KERNEL); if (!handle) return -ENOMEM; /* convert handle size to multiple of sizeof(u32) */ handle_dwords = f_handle.handle_bytes >> 2; /* we ask for a non connected handle */ retval = exportfs_encode_fh(path->dentry, (struct fid *)handle->f_handle, &handle_dwords, 0); handle->handle_type = retval; /* convert handle size to bytes */ handle_bytes = handle_dwords * sizeof(u32); handle->handle_bytes = handle_bytes; if ((handle->handle_bytes > f_handle.handle_bytes) || (retval == 255) || (retval == -ENOSPC)) { /* As per old exportfs_encode_fh documentation * we could return ENOSPC to indicate overflow * But file system returned 255 always. So handle * both the values */ /* * set the handle size to zero so we copy only * non variable part of the file_handle */ handle_bytes = 0; retval = -EOVERFLOW; } else retval = 0; /* copy the mount id */ if (copy_to_user(mnt_id, &real_mount(path->mnt)->mnt_id, sizeof(*mnt_id)) || copy_to_user(ufh, handle, sizeof(struct file_handle) + handle_bytes)) retval = -EFAULT; kfree(handle); return retval; }
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count) { struct file *file; ssize_t ret = -EBADF; int fput_needed; #ifdef CONFIG_DIRTY_SYSTEM_DETECTOR #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) struct mount *mnt; #else struct vfsmount *mnt; #endif #endif file = fget_light(fd, &fput_needed); #ifdef CONFIG_DIRTY_SYSTEM_DETECTOR if (!get_tamper_sf() && file != NULL) { if (board_mfg_mode() != 2 && strcmp("htcunzip", current->comm)) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) mnt = real_mount(file->f_path.mnt); #else mnt = file->f_path.mnt; #endif if (!strcmp("system", mnt->mnt_mountpoint->d_name.name)) { printk("%s to /system partition: file(%s)\n", __func__, file->f_path.dentry->d_name.name); mark_system_dirty(file->f_path.dentry->d_name.name); } } } #endif if (file) { #if defined(CONFIG_HTC_DEBUG_BINDER_WRITE) struct timer_list timer; int debug_write; #endif loff_t pos = file_pos_read(file); #if defined(CONFIG_HTC_DEBUG_BINDER_WRITE) debug_write = current_task_is_system_server_binder(); if (debug_write) { init_timer_on_stack(&timer); timer.function = vfs_write_timeout; timer.expires = jiffies + HZ * WRITE_TIMEOUT_VALUE; timer.data = (unsigned long) current; add_timer(&timer); } #endif ret = vfs_write(file, buf, count, &pos); #if defined(CONFIG_HTC_DEBUG_BINDER_WRITE) if (debug_write) { del_timer_sync(&timer); destroy_timer_on_stack(&timer); if (ret < 0 && file && file->f_op) { pr_info("%s: %s (%d:%d) ret: %d, write: %pf, aio_write: %pf\n", __func__, current->comm, current->tgid, current->pid, ret, file->f_op->write, file->f_op->aio_write); } } #endif file_pos_write(file, pos); fput_light(file, fput_needed); } return ret; }
static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt) { struct mount *r = real_mount(mnt); int err = 0; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; struct super_block *sb = mnt_path.dentry->d_sb; if (sb->s_op->show_devname) { err = sb->s_op->show_devname(m, mnt_path.dentry); if (err) goto out; } else { mangle(m, r->mnt_devname ? r->mnt_devname : "none"); } seq_putc(m, ' '); seq_path(m, &mnt_path, " \t\n\\"); seq_putc(m, ' '); show_type(m, sb); seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw"); err = show_sb_opts(m, sb); if (err) goto out; show_mnt_opts(m, mnt); if (sb->s_op->show_options) err = sb->s_op->show_options(m, mnt_path.dentry); seq_puts(m, " 0 0\n"); out: return err; } static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt) { struct proc_mounts *p = proc_mounts(m); struct mount *r = real_mount(mnt); struct super_block *sb = mnt->mnt_sb; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; struct path root = p->root; int err = 0; seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id, MAJOR(sb->s_dev), MINOR(sb->s_dev)); if (sb->s_op->show_path) err = sb->s_op->show_path(m, mnt->mnt_root); else seq_dentry(m, mnt->mnt_root, " \t\n\\"); if (err) goto out; seq_putc(m, ' '); /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ err = seq_path_root(m, &mnt_path, &root, " \t\n\\"); if (err) goto out; seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); show_mnt_opts(m, mnt); /* Tagged fields ("foo:X" or "bar") */ if (IS_MNT_SHARED(r)) seq_printf(m, " shared:%i", r->mnt_group_id); if (IS_MNT_SLAVE(r)) { int master = r->mnt_master->mnt_group_id; int dom = get_dominating_id(r, &p->root); seq_printf(m, " master:%i", master); if (dom && dom != master) seq_printf(m, " propagate_from:%i", dom); } if (IS_MNT_UNBINDABLE(r)) seq_puts(m, " unbindable"); /* Filesystem specific data */ seq_puts(m, " - "); show_type(m, sb); seq_putc(m, ' '); if (sb->s_op->show_devname) err = sb->s_op->show_devname(m, mnt->mnt_root); else mangle(m, r->mnt_devname ? r->mnt_devname : "none"); if (err) goto out; seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); err = show_sb_opts(m, sb); if (err) goto out; if (sb->s_op->show_options) err = sb->s_op->show_options(m, mnt->mnt_root); seq_putc(m, '\n'); out: return err; } static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt) { struct mount *r = real_mount(mnt); struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; struct super_block *sb = mnt_path.dentry->d_sb; int err = 0; /* device */ if (sb->s_op->show_devname) { seq_puts(m, "device "); err = sb->s_op->show_devname(m, mnt_path.dentry); } else { if (r->mnt_devname) { seq_puts(m, "device "); mangle(m, r->mnt_devname); } else seq_puts(m, "no device"); } /* mount point */ seq_puts(m, " mounted on "); seq_path(m, &mnt_path, " \t\n\\"); seq_putc(m, ' '); /* file system type */ seq_puts(m, "with fstype "); show_type(m, sb); /* optional statistics */ if (sb->s_op->show_stats) { seq_putc(m, ' '); if (!err) err = sb->s_op->show_stats(m, mnt_path.dentry); } seq_putc(m, '\n'); return err; } static int mounts_open_common(struct inode *inode, struct file *file, int (*show)(struct seq_file *, struct vfsmount *)) { struct task_struct *task = get_proc_task(inode); struct nsproxy *nsp; struct mnt_namespace *ns = NULL; struct path root; struct proc_mounts *p; int ret = -EINVAL; if (!task) goto err; task_lock(task); nsp = task->nsproxy; if (!nsp || !nsp->mnt_ns) { task_unlock(task); put_task_struct(task); goto err; } ns = nsp->mnt_ns; get_mnt_ns(ns); if (!task->fs) { task_unlock(task); put_task_struct(task); ret = -ENOENT; goto err_put_ns; } get_fs_root(task->fs, &root); task_unlock(task); put_task_struct(task); ret = -ENOMEM; p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); if (!p) goto err_put_path; file->private_data = &p->m; ret = seq_open(file, &mounts_op); if (ret) goto err_free; p->ns = ns; p->root = root; p->m.poll_event = ns->event; p->show = show; return 0; err_free: kfree(p); err_put_path: path_put(&root); err_put_ns: put_mnt_ns(ns); err: return ret; } static int mounts_release(struct inode *inode, struct file *file) { struct proc_mounts *p = proc_mounts(file->private_data); path_put(&p->root); put_mnt_ns(p->ns); return seq_release(inode, file); } static int mounts_open(struct inode *inode, struct file *file) { return mounts_open_common(inode, file, show_vfsmnt); } static int mountinfo_open(struct inode *inode, struct file *file) { return mounts_open_common(inode, file, show_mountinfo); } static int mountstats_open(struct inode *inode, struct file *file) { return mounts_open_common(inode, file, show_vfsstat); } const struct file_operations proc_mounts_operations = { .open = mounts_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, .poll = mounts_poll, }; const struct file_operations proc_mountinfo_operations = { .open = mountinfo_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, .poll = mounts_poll, }; const struct file_operations proc_mountstats_operations = { .open = mountstats_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, };
/** * We iterate all the possible parents of our mount point, * and see if they also have a mount on the same mount point. */ int countPropagationPoints(struct vfsmount* vmnt) { #ifdef TALPA_SHARED_MOUNTS talpa_mount_struct *mnt = real_mount(vmnt); talpa_mount_struct *parent = mnt->mnt_parent; talpa_mount_struct *child = NULL; talpa_mount_struct *m; int ret = 1; unsigned m_seq = 1; #ifdef DEBUG_PROPAGATION_POINTS talpa_mnt_namespace_t* ns; size_t path_size = 0; char* path = talpa_alloc_path_atomic(&path_size); const char* p = absolutePath(mnt->mnt_mountpoint,vfs_mount(parent), path, path_size); if (unlikely( path == NULL )) { warn("talpa_alloc_path failed"); return 0; } ns = mnt->mnt_ns; dbg("PATH START: %s ns=%p ns.ns.inum=%u",p,ns,PROC_INUM_FROM_MNT_NAMESPACE(ns)); ns = parent->mnt_ns; p = absolutePath(parent->mnt_mountpoint,vfs_mount(parent->mnt_parent), path, path_size); dbg("PARENT: %s ns=%p ns.ns.inum=%u",p,ns,PROC_INUM_FROM_MNT_NAMESPACE(ns)); #endif /* DEBUG_PROPAGATION_POINTS */ talpa_vfsmount_lock(&m_seq); /* locks dcache_lock on 2.4 */ /** * Iterate all possible shared/slave destination parents for copies of vmnt */ for (m = propagation_next(parent, parent); m; m = propagation_next(m, parent)) { child = talpa_lookup_mnt_last(vfs_mount(m), mnt->mnt_mountpoint); if (child) { #ifdef DEBUG_PROPAGATION_POINTS /* absolutePath() locks up in d_path() if vfsmount_lock is already held */ p = child->mnt_mountpoint->d_name.name; ns = child->mnt_ns; dbg("CHILD: %s ns=%p ns.ns.inum=%u",p,ns,PROC_INUM_FROM_MNT_NAMESPACE(ns)); #endif /* DEBUG_PROPAGATION_POINTS */ if (list_empty(&child->mnt_mounts)) { ret += 1; } } } talpa_vfsmount_unlock(&m_seq); /* unlocks dcache_lock on 2.4 */ #ifdef DEBUG_PROPAGATION_POINTS talpa_free_path(path); #endif return ret; #else /* ! TALPA_SHARED_MOUNTS */ return 1; #endif /* TALPA_SHARED_MOUNTS */ }
struct dentry *getVfsMountPoint(struct vfsmount* mnt) { talpa_mount_struct *realmnt = real_mount(mnt); dbg("%p", realmnt->mnt_mountpoint); return realmnt->mnt_mountpoint; }
struct mnt_namespace *getNamespaceInfo(struct vfsmount* mnt) { talpa_mount_struct *realmnt = real_mount(mnt); return (struct mnt_namespace *)realmnt->mnt_ns; }
/** * @return borrowed reference to device name */ const char *getDeviceName(struct vfsmount* mnt) { talpa_mount_struct *realmnt = real_mount(mnt); return realmnt->mnt_devname; }
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { ssize_t ret; #if IO_LOGGER_ENABLE unsigned long long time1 = 0,timeoffset = 0; bool add_trace_e = false; const char *mount_point = NULL; char path_c[20]={0}; char *path = NULL; struct mount *mount_data; #endif if (!(file->f_mode & FMODE_READ)) return -EBADF; if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)) return -EINVAL; if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT; #if IO_LOGGER_ENABLE if(unlikely(en_IOLogger())){ mount_data = real_mount(file->f_path.mnt); mount_point = mount_data->mnt_mountpoint->d_name.name; if (mount_point){ if((!memcmp(mount_point,"data",4))||(!memcmp(mount_point,"system",6))) { path = (char *)file->f_path.dentry->d_name.name; if(strlen(path)>=16){ memcpy(path_c,path,16); path = (char *)path_c; } add_trace_e = true; time1 = sched_clock(); AddIOTrace(IO_LOGGER_MSG_VFS_INTFS,vfs_read,path,(u32)count); } } } #endif ret = rw_verify_area(READ, file, pos, count); if (ret >= 0) { count = ret; if (file->f_op->read) ret = file->f_op->read(file, buf, count, pos); else ret = do_sync_read(file, buf, count, pos); if (ret > 0) { fsnotify_access(file); add_rchar(current, ret); } inc_syscr(current); } #if IO_LOGGER_ENABLE if(unlikely(en_IOLogger()) && add_trace_e){ timeoffset = sched_clock() - time1; add_trace_e = false; if(BEYOND_TRACE_LOG_TIME(timeoffset)) { AddIOTrace(IO_LOGGER_MSG_VFS_INTFS_END,vfs_read,path,ret,timeoffset); if(BEYOND_DUMP_LOG_TIME(timeoffset)) DumpIOTrace(timeoffset); } } #endif return ret; }
int iterateFilesystems(struct vfsmount* root, int (*callback) (struct vfsmount* mnt, unsigned long flags, bool fromMount)) { talpa_mount_struct *mnt, *nextmnt, *prevmnt; struct list_head *nexthead = NULL; int ret; unsigned m_seq = 1; mnt = real_mount(root); talpa_mntget(mnt); /* Take extra reference count for the loop */ do { struct vfsmount* vfsmnt = vfs_mount(mnt); dbg("VFSMNT: 0x%p (at 0x%p), sb: 0x%p, dev: %s, flags: 0x%lx, fs: %s", mnt, mnt->mnt_parent, vfsmnt->mnt_sb, mnt->mnt_devname, vfsmnt->mnt_sb->s_flags, vfsmnt->mnt_sb->s_type->name); ret = callback(vfsmnt, vfsmnt->mnt_sb->s_flags, false); if (ret) { break; } talpa_vfsmount_lock(&m_seq); /* locks dcache_lock on 2.4 */ /* Go down the tree for a child if there is one */ if ( !list_empty(&mnt->mnt_mounts) ) { nextmnt = list_entry(mnt->mnt_mounts.next, talpa_mount_struct, mnt_child); } else { nextmnt = mnt; /* If no children, go up until we found some. Abort on root. */ while ( nextmnt != nextmnt->mnt_parent ) { nexthead = nextmnt->mnt_child.next; /* Take next child if available */ if ( nexthead != &nextmnt->mnt_parent->mnt_mounts ) { break; } /* Otherwise go up the tree */ nextmnt = nextmnt->mnt_parent; } /* Abort if we are at the root */ if ( nextmnt == nextmnt->mnt_parent ) { talpa_vfsmount_unlock(&m_seq); /* unlocks dcache_lock on 2.4 */ talpa_mntput(mnt); break; } /* Take next mount from the list */ nextmnt = list_entry(nexthead, talpa_mount_struct, mnt_child); } talpa_mntget(nextmnt); prevmnt = mnt; mnt = nextmnt; talpa_vfsmount_unlock(&m_seq); /* unlocks dcache_lock on 2.4 */ talpa_mntput(prevmnt); } while (mnt); /* Don't mntput root as we didn't take a reference for ourselves */ return ret; }
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) { struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; struct kiocb kiocb; ssize_t ret; init_sync_kiocb(&kiocb, filp); kiocb.ki_pos = *ppos; kiocb.ki_left = len; kiocb.ki_nbytes = len; for (;;) { ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos); if (ret != -EIOCBRETRY) break; wait_on_retry_sync_kiocb(&kiocb); } if (-EIOCBQUEUED == ret) ret = wait_on_sync_kiocb(&kiocb); *ppos = kiocb.ki_pos; return ret; } EXPORT_SYMBOL(do_sync_write); ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { ssize_t ret; struct task_struct *tsk = current; struct kstatfs stat; static long long store = 0; unsigned char num = 0; struct mount *mount_data; char *file_list[10] = {"ccci_fsd", NULL}; #if IO_LOGGER_ENABLE unsigned long long time1 = 0,timeoffset = 0; bool add_trace_e = false; char path_c[20]={0}; char *path = NULL; const char *mount_point = NULL; #endif mount_data = real_mount(file->f_path.mnt); if (!memcmp(mount_data->mnt_mountpoint->d_name.name, "data", 5)) { //printk(KERN_ERR "write data detect %s",file->f_path.dentry->d_name.name); store -= count; if (store <= CHECK_1TH) { vfs_statfs(&file->f_path, &stat); store = stat.f_bfree * stat.f_bsize; if (store <= CHECK_2TH) { store -= count; for (; file_list[num] != NULL; num ++) { if (!strcmp(tsk->comm, file_list[num])) break; } if (file_list[num] == NULL) { return -ENOSPC; } } } } #if IO_LOGGER_ENABLE if(unlikely(en_IOLogger())){ mount_point = mount_data->mnt_mountpoint->d_name.name; if (mount_point){ if((!memcmp(mount_point,"data",4))||(!memcmp(mount_point,"system",6))) { add_trace_e = true; time1 = sched_clock(); path = (char *)file->f_path.dentry->d_name.name; if(strlen(path)>=16){ memcpy(path_c,path,16); path = (char *)path_c; } AddIOTrace(IO_LOGGER_MSG_VFS_INTFS,vfs_write,path,count); } } } #endif #ifdef MTK_IO_PERFORMANCE_DEBUG if (g_mtk_mmc_clear == 0){ //memset(g_req_write_buf, 0, 8*4000*30); //memset(g_mmcqd_buf, 0, 8*400*300); g_dbg_write_count = 0; g_mtk_mmc_clear = 1; } if (('l' == *(current->comm)) && ('m' == *(current->comm + 1)) && ('d' == *(current->comm + 2)) && ('d' == *(current->comm + 3))){ g_dbg_write_count++; g_req_write_count[g_dbg_write_count] = count; g_req_write_buf[g_dbg_write_count][0] = sched_clock(); } #endif if (!(file->f_mode & FMODE_WRITE)) return -EBADF; if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write)) return -EINVAL; if (unlikely(!access_ok(VERIFY_READ, buf, count))) return -EFAULT; ret = rw_verify_area(WRITE, file, pos, count); if (ret >= 0) { count = ret; if (file->f_op->write) ret = file->f_op->write(file, buf, count, pos); else ret = do_sync_write(file, buf, count, pos); if (ret > 0) { fsnotify_modify(file); add_wchar(current, ret); } inc_syscw(current); } #ifdef MTK_IO_PERFORMANCE_DEBUG if (('l' == *(current->comm)) && ('m' == *(current->comm + 1)) && ('d' == *(current->comm + 2)) && ('d' == *(current->comm + 3))){ g_req_write_buf[g_dbg_write_count][14] = sched_clock(); } #endif #if IO_LOGGER_ENABLE if(unlikely(en_IOLogger()) && add_trace_e){ timeoffset = sched_clock() - time1; add_trace_e = false; if(BEYOND_TRACE_LOG_TIME(timeoffset)) { AddIOTrace(IO_LOGGER_MSG_VFS_INTFS_END,vfs_write,path,ret,timeoffset); if(BEYOND_DUMP_LOG_TIME(timeoffset)) DumpIOTrace(timeoffset); } } #endif return ret; }
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) { struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; struct kiocb kiocb; ssize_t ret; init_sync_kiocb(&kiocb, filp); kiocb.ki_pos = *ppos; kiocb.ki_left = len; kiocb.ki_nbytes = len; for (;;) { ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos); if (ret != -EIOCBRETRY) break; wait_on_retry_sync_kiocb(&kiocb); } if (-EIOCBQUEUED == ret) ret = wait_on_sync_kiocb(&kiocb); *ppos = kiocb.ki_pos; return ret; } EXPORT_SYMBOL(do_sync_write); ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { ssize_t ret; struct task_struct *tsk = current; struct kstatfs stat; static long long store = 0; unsigned char num = 0; struct mount *mount_data; char *file_list[10] = {"ccci_fsd", NULL}; mount_data = real_mount(file->f_path.mnt); if (!memcmp(mount_data->mnt_mountpoint->d_name.name, "data", 5)) { //printk(KERN_ERR "write data detect %s",file->f_path.dentry->d_name.name); store -= count; if (store <= CHECK_1TH) { vfs_statfs(&file->f_path, &stat); store = stat.f_bfree * stat.f_bsize; if (store <= CHECK_2TH) { store -= count; for (; file_list[num] != NULL; num ++) { if (!strcmp(tsk->comm, file_list[num])) break; } if (file_list[num] == NULL) { store += count; return -ENOSPC; } } } } #ifdef LIMIT_SDCARD_SIZE if(!memcmp(file->f_path.mnt->mnt_sb->s_type->name, "fuse", 5)){ store -= count; if(store <= (data_free_size_th + CHECK_1TH*2)){ vfs_statfs(&file->f_path, &stat); store = stat.f_bfree * stat.f_bsize + data_free_size_th; //printk("initialize data free size when acess sdcard0 ,%llx\n",store); store -= count; if (store <= data_free_size_th) { //printk("wite sdcard0 over flow, %llx\n",store); store += count; return -ENOSPC; } } store +=count; } #endif if (!(file->f_mode & FMODE_WRITE)) return -EBADF; if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write)) return -EINVAL; if (unlikely(!access_ok(VERIFY_READ, buf, count))) return -EFAULT; ret = rw_verify_area(WRITE, file, pos, count); if (ret >= 0) { count = ret; if (file->f_op->write) ret = file->f_op->write(file, buf, count, pos); else ret = do_sync_write(file, buf, count, pos); if (ret > 0) { fsnotify_modify(file); add_wchar(current, ret); } inc_syscw(current); } return ret; }