diff options
Diffstat (limited to 'fs/jfs/namei.c')
-rw-r--r-- | fs/jfs/namei.c | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 231ca4af9bce..eaaf2b511e89 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -18,6 +18,7 @@ */ #include <linux/fs.h> +#include <linux/namei.h> #include <linux/ctype.h> #include <linux/quotaops.h> #include <linux/exportfs.h> @@ -114,7 +115,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, if (rc) goto out3; - rc = jfs_init_security(tid, ip, dip); + rc = jfs_init_security(tid, ip, dip, &dentry->d_name); if (rc) { txAbort(tid, 0); goto out3; @@ -252,7 +253,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) if (rc) goto out3; - rc = jfs_init_security(tid, ip, dip); + rc = jfs_init_security(tid, ip, dip, &dentry->d_name); if (rc) { txAbort(tid, 0); goto out3; @@ -808,9 +809,6 @@ static int jfs_link(struct dentry *old_dentry, if (ip->i_nlink == JFS_LINK_MAX) return -EMLINK; - if (ip->i_nlink == 0) - return -ENOENT; - dquot_initialize(dir); tid = txBegin(ip->i_sb, 0); @@ -931,7 +929,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); - rc = jfs_init_security(tid, ip, dip); + rc = jfs_init_security(tid, ip, dip, &dentry->d_name); if (rc) goto out3; @@ -1394,7 +1392,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, if (rc) goto out3; - rc = jfs_init_security(tid, ip, dir); + rc = jfs_init_security(tid, ip, dir, &dentry->d_name); if (rc) { txAbort(tid, 0); goto out3; @@ -1464,9 +1462,6 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc jfs_info("jfs_lookup: name = %s", name); - if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2) - dentry->d_op = &jfs_ci_dentry_operations; - if ((name[0] == '.') && (len == 1)) inum = dip->i_ino; else if (strcmp(name, "..") == 0) @@ -1491,12 +1486,7 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc return ERR_CAST(ip); } - dentry = d_splice_alias(ip, dentry); - - if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)) - dentry->d_op = &jfs_ci_dentry_operations; - - return dentry; + return d_splice_alias(ip, dentry); } static struct inode *jfs_nfs_get_inode(struct super_block *sb, @@ -1573,7 +1563,8 @@ const struct file_operations jfs_dir_operations = { .llseek = generic_file_llseek, }; -static int jfs_ci_hash(struct dentry *dir, struct qstr *this) +static int jfs_ci_hash(const struct dentry *dir, const struct inode *inode, + struct qstr *this) { unsigned long hash; int i; @@ -1586,32 +1577,63 @@ static int jfs_ci_hash(struct dentry *dir, struct qstr *this) return 0; } -static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b) +static int jfs_ci_compare(const struct dentry *parent, + const struct inode *pinode, + const struct dentry *dentry, const struct inode *inode, + unsigned int len, const char *str, const struct qstr *name) { int i, result = 1; - if (a->len != b->len) + if (len != name->len) goto out; - for (i=0; i < a->len; i++) { - if (tolower(a->name[i]) != tolower(b->name[i])) + for (i=0; i < len; i++) { + if (tolower(str[i]) != tolower(name->name[i])) goto out; } result = 0; +out: + return result; +} +static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd) +{ + if (nd && nd->flags & LOOKUP_RCU) + return -ECHILD; /* - * We want creates to preserve case. A negative dentry, a, that - * has a different case than b may cause a new entry to be created - * with the wrong case. Since we can't tell if a comes from a negative - * dentry, we blindly replace it with b. This should be harmless if - * a is not a negative dentry. + * This is not negative dentry. Always valid. + * + * Note, rename() to existing directory entry will have ->d_inode, + * and will use existing name which isn't specified name by user. + * + * We may be able to drop this positive dentry here. But dropping + * positive dentry isn't good idea. So it's unsupported like + * rename("filename", "FILENAME") for now. */ - memcpy((unsigned char *)a->name, b->name, a->len); -out: - return result; + if (dentry->d_inode) + return 1; + + /* + * This may be nfsd (or something), anyway, we can't see the + * intent of this. So, since this can be for creation, drop it. + */ + if (!nd) + return 0; + + /* + * Drop the negative dentry, in order to make sure to use the + * case sensitive name which is specified by user if this is + * for creation. + */ + if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) { + if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) + return 0; + } + return 1; } const struct dentry_operations jfs_ci_dentry_operations = { .d_hash = jfs_ci_hash, .d_compare = jfs_ci_compare, + .d_revalidate = jfs_ci_revalidate, }; |