Loading fs/sdcardfs/dentry.c +9 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ /* * NOTE: This file has been modified by Sony Mobile Communications Inc. * Modifications are Copyright (c) 2018 Sony Mobile Communications Inc, * and licensed under the license of the file. */ #include "sdcardfs.h" #include "linux/ctype.h" Loading Loading @@ -126,7 +131,10 @@ out: /* 1 = delete, 0 = cache */ static int sdcardfs_d_delete(const struct dentry *d) { return SDCARDFS_SB(d->d_sb)->options.nocache ? 1 : 0; if (SDCARDFS_SB(d->d_sb)->options.nocache) return d->d_inode && !S_ISDIR(d->d_inode->i_mode); return 0; } static void sdcardfs_d_release(struct dentry *dentry) Loading fs/sdcardfs/file.c +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ /* * NOTE: This file has been modified by Sony Mobile Communications Inc. * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc, * and licensed under the license of the file. */ #include "sdcardfs.h" #ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE Loading Loading @@ -255,6 +260,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file) goto out_err; } file->f_mode |= FMODE_NONMAPPABLE; file->private_data = kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); if (!SDCARDFS_F(file)) { Loading Loading @@ -432,6 +438,11 @@ out: return err; } static struct file *sdcardfs_get_lower_file(struct file *f) { return sdcardfs_lower_file(f); } const struct file_operations sdcardfs_main_fops = { .llseek = generic_file_llseek, .read = sdcardfs_read, Loading @@ -448,6 +459,7 @@ const struct file_operations sdcardfs_main_fops = { .fasync = sdcardfs_fasync, .read_iter = sdcardfs_read_iter, .write_iter = sdcardfs_write_iter, .get_lower_file = sdcardfs_get_lower_file, }; /* trimmed directory options */ Loading @@ -464,4 +476,5 @@ const struct file_operations sdcardfs_dir_fops = { .flush = sdcardfs_flush, .fsync = sdcardfs_fsync, .fasync = sdcardfs_fasync, .get_lower_file = sdcardfs_get_lower_file, }; fs/sdcardfs/inode.c +11 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ /* * NOTE: This file has been modified by Sony Mobile Communications Inc. * Modifications are Copyright (c) 2016 Sony Mobile Communications Inc, * and licensed under the license of the file. */ #include "sdcardfs.h" #include <linux/fs_struct.h> Loading Loading @@ -101,7 +106,7 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, current->fs = copied_fs; task_unlock(current); err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); err = vfs_create2(lower_dentry_mnt, lower_parent_dentry->d_inode, lower_dentry, mode, want_excl); if (err) goto out; Loading Loading @@ -259,7 +264,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode current->fs = copied_fs; task_unlock(current); err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode); err = vfs_mkdir2(lower_mnt, lower_parent_dentry->d_inode, lower_dentry, mode); if (err) { unlock_dir(lower_parent_dentry); Loading Loading @@ -770,7 +775,11 @@ static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry, goto out; sdcardfs_copy_and_fix_attrs(d_inode(dentry), d_inode(lower_path.dentry)); fsstack_copy_inode_size(d_inode(dentry), d_inode(lower_path.dentry)); err = sdcardfs_fillattr(mnt, d_inode(dentry), &lower_stat, stat); fsstack_copy_inode_size(d_inode(dentry), d_inode(lower_path.dentry)); out: sdcardfs_put_lower_path(dentry, &lower_path); return err; Loading fs/sdcardfs/lookup.c +123 −0 Original line number Diff line number Diff line Loading @@ -17,9 +17,15 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ /* * NOTE: This file has been modified by Sony Mobile Communications Inc. * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc, * and licensed under the license of the file. */ #include "sdcardfs.h" #include "linux/delay.h" #include <linux/limits.h> /* The dentry cache is just so we have properly sized dentries */ static struct kmem_cache *sdcardfs_dentry_cachep; Loading Loading @@ -112,6 +118,10 @@ struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, u /* if found a cached inode, then just return it (after iput) */ if (!(inode->i_state & I_NEW)) { iput(lower_inode); /* There can only be one alias, as we don't permit hard links * This ensures we do not keep stale dentries that would later * cause confusion. */ d_prune_aliases(inode); return inode; } Loading Loading @@ -242,6 +252,89 @@ static int sdcardfs_name_match(struct dir_context *ctx, const char *name, return 0; } /* The dir context used by sdcardfs_lower_filldir() */ struct sdcardfs_lower_getent_cb { struct dir_context ctx; loff_t pos; const char *target; /* search target */ int target_len; char alias[NAME_MAX+1]; /* alias name found in lower dir */ int alias_len; int result; /* 0: found, -ENOENT: not found. */ }; /* The filldir used by case insensitive search in sdcardfs_ci_path_lookup() */ static int sdcardfs_lower_filldir(struct dir_context *ctx, const char *name, int namelen, loff_t offset, u64 ino, unsigned int d_type) { struct sdcardfs_lower_getent_cb *buf; buf = container_of(ctx, struct sdcardfs_lower_getent_cb, ctx); if (!buf->result) /* entry already found, skip search */ return 0; buf->pos = buf->ctx.pos; if (!strncasecmp(name, buf->target, namelen) && namelen == buf->target_len) { strlcpy(buf->alias, name, namelen + 1); buf->alias_len = namelen; buf->result = 0; /* 0: found matching entry */ } return 0; } /* * Case insentively lookup lower directory. * * @folder: path to the lower folder. * @name: lookup name. * @entry: path to the found entry. * * Returns: 0 (ok), -ENOENT (entry not found) */ static int sdcardfs_ci_path_lookup(struct path *folder, const char *name, struct path *entry) { int ret = 0; struct file *filp; loff_t last_pos; struct sdcardfs_lower_getent_cb buf = { .ctx.actor = sdcardfs_lower_filldir, .ctx.pos = 0, .pos = 0, .target = name, .alias_len = 0, .result = -ENOENT }; buf.target_len = strlen(name); filp = dentry_open(folder, O_RDONLY | O_DIRECTORY, current_cred()); if (IS_ERR_OR_NULL(filp)) return -ENOENT; while (ret >= 0) { last_pos = filp->f_pos; ret = iterate_dir(filp, &buf.ctx); /* reaches end or found matching entry */ if (last_pos == filp->f_pos || !buf.result) break; } filp_close(filp, NULL); if (!buf.result) return vfs_path_lookup(folder->dentry, folder->mnt, buf.alias, 0, entry); else return buf.result; } /* * Main driver function for sdcardfs's lookup. * Loading Loading @@ -314,6 +407,36 @@ put_name: __putname(buffer.name); } /* If the dentry was not found, and the intent is not rename file, * try case insensitive search in lower parent directory. */ if ((err == -ENOENT) && !(flags & LOOKUP_RENAME_TARGET)) err = sdcardfs_ci_path_lookup(lower_parent_path, name->name, &lower_path); #if 0 /* check for other cases */ if (err == -ENOENT) { struct dentry *child; struct dentry *match = NULL; spin_lock(&lower_dir_dentry->d_lock); list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) { if (child && child->d_inode) { if (strcasecmp(child->d_name.name, name)==0) { match = dget(child); break; } } } spin_unlock(&lower_dir_dentry->d_lock); if (match) { err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, match->d_name.name, 0, &lower_path); dput(match); } } #endif /* no error: handle positive dentries */ if (!err) { /* check if the dentry is an obb dentry Loading Loading
fs/sdcardfs/dentry.c +9 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ /* * NOTE: This file has been modified by Sony Mobile Communications Inc. * Modifications are Copyright (c) 2018 Sony Mobile Communications Inc, * and licensed under the license of the file. */ #include "sdcardfs.h" #include "linux/ctype.h" Loading Loading @@ -126,7 +131,10 @@ out: /* 1 = delete, 0 = cache */ static int sdcardfs_d_delete(const struct dentry *d) { return SDCARDFS_SB(d->d_sb)->options.nocache ? 1 : 0; if (SDCARDFS_SB(d->d_sb)->options.nocache) return d->d_inode && !S_ISDIR(d->d_inode->i_mode); return 0; } static void sdcardfs_d_release(struct dentry *dentry) Loading
fs/sdcardfs/file.c +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ /* * NOTE: This file has been modified by Sony Mobile Communications Inc. * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc, * and licensed under the license of the file. */ #include "sdcardfs.h" #ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE Loading Loading @@ -255,6 +260,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file) goto out_err; } file->f_mode |= FMODE_NONMAPPABLE; file->private_data = kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); if (!SDCARDFS_F(file)) { Loading Loading @@ -432,6 +438,11 @@ out: return err; } static struct file *sdcardfs_get_lower_file(struct file *f) { return sdcardfs_lower_file(f); } const struct file_operations sdcardfs_main_fops = { .llseek = generic_file_llseek, .read = sdcardfs_read, Loading @@ -448,6 +459,7 @@ const struct file_operations sdcardfs_main_fops = { .fasync = sdcardfs_fasync, .read_iter = sdcardfs_read_iter, .write_iter = sdcardfs_write_iter, .get_lower_file = sdcardfs_get_lower_file, }; /* trimmed directory options */ Loading @@ -464,4 +476,5 @@ const struct file_operations sdcardfs_dir_fops = { .flush = sdcardfs_flush, .fsync = sdcardfs_fsync, .fasync = sdcardfs_fasync, .get_lower_file = sdcardfs_get_lower_file, };
fs/sdcardfs/inode.c +11 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ /* * NOTE: This file has been modified by Sony Mobile Communications Inc. * Modifications are Copyright (c) 2016 Sony Mobile Communications Inc, * and licensed under the license of the file. */ #include "sdcardfs.h" #include <linux/fs_struct.h> Loading Loading @@ -101,7 +106,7 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, current->fs = copied_fs; task_unlock(current); err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); err = vfs_create2(lower_dentry_mnt, lower_parent_dentry->d_inode, lower_dentry, mode, want_excl); if (err) goto out; Loading Loading @@ -259,7 +264,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode current->fs = copied_fs; task_unlock(current); err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode); err = vfs_mkdir2(lower_mnt, lower_parent_dentry->d_inode, lower_dentry, mode); if (err) { unlock_dir(lower_parent_dentry); Loading Loading @@ -770,7 +775,11 @@ static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry, goto out; sdcardfs_copy_and_fix_attrs(d_inode(dentry), d_inode(lower_path.dentry)); fsstack_copy_inode_size(d_inode(dentry), d_inode(lower_path.dentry)); err = sdcardfs_fillattr(mnt, d_inode(dentry), &lower_stat, stat); fsstack_copy_inode_size(d_inode(dentry), d_inode(lower_path.dentry)); out: sdcardfs_put_lower_path(dentry, &lower_path); return err; Loading
fs/sdcardfs/lookup.c +123 −0 Original line number Diff line number Diff line Loading @@ -17,9 +17,15 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ /* * NOTE: This file has been modified by Sony Mobile Communications Inc. * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc, * and licensed under the license of the file. */ #include "sdcardfs.h" #include "linux/delay.h" #include <linux/limits.h> /* The dentry cache is just so we have properly sized dentries */ static struct kmem_cache *sdcardfs_dentry_cachep; Loading Loading @@ -112,6 +118,10 @@ struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, u /* if found a cached inode, then just return it (after iput) */ if (!(inode->i_state & I_NEW)) { iput(lower_inode); /* There can only be one alias, as we don't permit hard links * This ensures we do not keep stale dentries that would later * cause confusion. */ d_prune_aliases(inode); return inode; } Loading Loading @@ -242,6 +252,89 @@ static int sdcardfs_name_match(struct dir_context *ctx, const char *name, return 0; } /* The dir context used by sdcardfs_lower_filldir() */ struct sdcardfs_lower_getent_cb { struct dir_context ctx; loff_t pos; const char *target; /* search target */ int target_len; char alias[NAME_MAX+1]; /* alias name found in lower dir */ int alias_len; int result; /* 0: found, -ENOENT: not found. */ }; /* The filldir used by case insensitive search in sdcardfs_ci_path_lookup() */ static int sdcardfs_lower_filldir(struct dir_context *ctx, const char *name, int namelen, loff_t offset, u64 ino, unsigned int d_type) { struct sdcardfs_lower_getent_cb *buf; buf = container_of(ctx, struct sdcardfs_lower_getent_cb, ctx); if (!buf->result) /* entry already found, skip search */ return 0; buf->pos = buf->ctx.pos; if (!strncasecmp(name, buf->target, namelen) && namelen == buf->target_len) { strlcpy(buf->alias, name, namelen + 1); buf->alias_len = namelen; buf->result = 0; /* 0: found matching entry */ } return 0; } /* * Case insentively lookup lower directory. * * @folder: path to the lower folder. * @name: lookup name. * @entry: path to the found entry. * * Returns: 0 (ok), -ENOENT (entry not found) */ static int sdcardfs_ci_path_lookup(struct path *folder, const char *name, struct path *entry) { int ret = 0; struct file *filp; loff_t last_pos; struct sdcardfs_lower_getent_cb buf = { .ctx.actor = sdcardfs_lower_filldir, .ctx.pos = 0, .pos = 0, .target = name, .alias_len = 0, .result = -ENOENT }; buf.target_len = strlen(name); filp = dentry_open(folder, O_RDONLY | O_DIRECTORY, current_cred()); if (IS_ERR_OR_NULL(filp)) return -ENOENT; while (ret >= 0) { last_pos = filp->f_pos; ret = iterate_dir(filp, &buf.ctx); /* reaches end or found matching entry */ if (last_pos == filp->f_pos || !buf.result) break; } filp_close(filp, NULL); if (!buf.result) return vfs_path_lookup(folder->dentry, folder->mnt, buf.alias, 0, entry); else return buf.result; } /* * Main driver function for sdcardfs's lookup. * Loading Loading @@ -314,6 +407,36 @@ put_name: __putname(buffer.name); } /* If the dentry was not found, and the intent is not rename file, * try case insensitive search in lower parent directory. */ if ((err == -ENOENT) && !(flags & LOOKUP_RENAME_TARGET)) err = sdcardfs_ci_path_lookup(lower_parent_path, name->name, &lower_path); #if 0 /* check for other cases */ if (err == -ENOENT) { struct dentry *child; struct dentry *match = NULL; spin_lock(&lower_dir_dentry->d_lock); list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) { if (child && child->d_inode) { if (strcasecmp(child->d_name.name, name)==0) { match = dget(child); break; } } } spin_unlock(&lower_dir_dentry->d_lock); if (match) { err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, match->d_name.name, 0, &lower_path); dput(match); } } #endif /* no error: handle positive dentries */ if (!err) { /* check if the dentry is an obb dentry Loading