]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/fat/namei_vfat.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / fs / fat / namei_vfat.c
index b936703b8924491a2671b8432c67570d18e9a810..adae3fb7451aa52670d07fdf34381defe133e73a 100644 (file)
@@ -43,6 +43,9 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
 
 static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
+       if (nd && nd->flags & LOOKUP_RCU)
+               return -ECHILD;
+
        /* This is not negative dentry. Always valid. */
        if (dentry->d_inode)
                return 1;
@@ -51,6 +54,9 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
 
 static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
 {
+       if (nd && nd->flags & LOOKUP_RCU)
+               return -ECHILD;
+
        /*
         * This is not negative dentry. Always valid.
         *
@@ -85,22 +91,26 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
 }
 
 /* returns the length of a struct qstr, ignoring trailing dots */
-static unsigned int vfat_striptail_len(struct qstr *qstr)
+static unsigned int __vfat_striptail_len(unsigned int len, const char *name)
 {
-       unsigned int len = qstr->len;
-
-       while (len && qstr->name[len - 1] == '.')
+       while (len && name[len - 1] == '.')
                len--;
        return len;
 }
 
+static unsigned int vfat_striptail_len(const struct qstr *qstr)
+{
+       return __vfat_striptail_len(qstr->len, qstr->name);
+}
+
 /*
  * Compute the hash for the vfat name corresponding to the dentry.
  * Note: if the name is invalid, we leave the hash code unchanged so
  * that the existing dentry can be used. The vfat fs routines will
  * return ENOENT or EINVAL as appropriate.
  */
-static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
+static int vfat_hash(const struct dentry *dentry, const struct inode *inode,
+               struct qstr *qstr)
 {
        qstr->hash = full_name_hash(qstr->name, vfat_striptail_len(qstr));
        return 0;
@@ -112,9 +122,10 @@ static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
  * that the existing dentry can be used. The vfat fs routines will
  * return ENOENT or EINVAL as appropriate.
  */
-static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
+static int vfat_hashi(const struct dentry *dentry, const struct inode *inode,
+               struct qstr *qstr)
 {
-       struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
+       struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
        const unsigned char *name;
        unsigned int len;
        unsigned long hash;
@@ -133,16 +144,18 @@ static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
 /*
  * Case insensitive compare of two vfat names.
  */
-static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
+static int vfat_cmpi(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)
 {
-       struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
+       struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
        unsigned int alen, blen;
 
        /* A filename cannot end in '.' or we treat it like it has none */
-       alen = vfat_striptail_len(a);
-       blen = vfat_striptail_len(b);
+       alen = vfat_striptail_len(name);
+       blen = __vfat_striptail_len(len, str);
        if (alen == blen) {
-               if (nls_strnicmp(t, a->name, b->name, alen) == 0)
+               if (nls_strnicmp(t, name->name, str, alen) == 0)
                        return 0;
        }
        return 1;
@@ -151,15 +164,17 @@ static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
 /*
  * Case sensitive compare of two vfat names.
  */
-static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
+static int vfat_cmp(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)
 {
        unsigned int alen, blen;
 
        /* A filename cannot end in '.' or we treat it like it has none */
-       alen = vfat_striptail_len(a);
-       blen = vfat_striptail_len(b);
+       alen = vfat_striptail_len(name);
+       blen = __vfat_striptail_len(len, str);
        if (alen == blen) {
-               if (strncmp(a->name, b->name, alen) == 0)
+               if (strncmp(name->name, str, alen) == 0)
                        return 0;
        }
        return 1;
@@ -757,13 +772,10 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
 
 out:
        unlock_super(sb);
-       dentry->d_op = sb->s_root->d_op;
        dentry->d_time = dentry->d_parent->d_inode->i_version;
        dentry = d_splice_alias(inode, dentry);
-       if (dentry) {
-               dentry->d_op = sb->s_root->d_op;
+       if (dentry)
                dentry->d_time = dentry->d_parent->d_inode->i_version;
-       }
        return dentry;
 
 error:
@@ -1051,24 +1063,18 @@ static const struct inode_operations vfat_dir_inode_operations = {
        .getattr        = fat_getattr,
 };
 
-static int vfat_fill_super(struct super_block *sb, void *data, int silent)
+static void setup(struct super_block *sb)
 {
-       int res;
-
-       lock_super(sb);
-       res = fat_fill_super(sb, data, silent, &vfat_dir_inode_operations, 1);
-       if (res) {
-               unlock_super(sb);
-               return res;
-       }
-
        if (MSDOS_SB(sb)->options.name_check != 's')
-               sb->s_root->d_op = &vfat_ci_dentry_ops;
+               sb->s_d_op = &vfat_ci_dentry_ops;
        else
-               sb->s_root->d_op = &vfat_dentry_ops;
+               sb->s_d_op = &vfat_dentry_ops;
+}
 
-       unlock_super(sb);
-       return 0;
+static int vfat_fill_super(struct super_block *sb, void *data, int silent)
+{
+       return fat_fill_super(sb, data, silent, &vfat_dir_inode_operations,
+                            1, setup);
 }
 
 static struct dentry *vfat_mount(struct file_system_type *fs_type,