Merge remote-tracking branch 'sound-asoc/for-next'
[deliverable/linux.git] / fs / nfs / dir.c
index 19d93d0cd400f5ac175a9d257ec8a8ced0e04c21..06e0bf092ba90151b91baf848990024cc4abf416 100644 (file)
@@ -232,7 +232,7 @@ int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int le
         * in a page cache page which kmemleak does not scan.
         */
        kmemleak_not_leak(string->name);
-       string->hash = full_name_hash(name, len);
+       string->hash = full_name_hash(NULL, name, len);
        return 0;
 }
 
@@ -502,7 +502,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
                if (filename.len == 2 && filename.name[1] == '.')
                        return;
        }
-       filename.hash = full_name_hash(filename.name, filename.len);
+       filename.hash = full_name_hash(parent, filename.name, filename.len);
 
        dentry = d_lookup(parent, &filename);
 again:
@@ -734,7 +734,7 @@ struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
        struct page *page;
 
        for (;;) {
-               page = read_cache_page(file_inode(desc->file)->i_mapping,
+               page = read_cache_page(desc->file->f_mapping,
                        desc->page_index, (filler_t *)nfs_readdir_filler, desc);
                if (IS_ERR(page) || grab_page(page))
                        break;
@@ -1397,19 +1397,18 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
        if (IS_ERR(label))
                goto out;
 
-       /* Protect against concurrent sillydeletes */
        trace_nfs_lookup_enter(dir, dentry, flags);
        error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
        if (error == -ENOENT)
                goto no_entry;
        if (error < 0) {
                res = ERR_PTR(error);
-               goto out_unblock_sillyrename;
+               goto out_label;
        }
        inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label);
        res = ERR_CAST(inode);
        if (IS_ERR(res))
-               goto out_unblock_sillyrename;
+               goto out_label;
 
        /* Success: notify readdir to use READDIRPLUS */
        nfs_advise_use_readdirplus(dir);
@@ -1418,11 +1417,11 @@ no_entry:
        res = d_splice_alias(inode, dentry);
        if (res != NULL) {
                if (IS_ERR(res))
-                       goto out_unblock_sillyrename;
+                       goto out_label;
                dentry = res;
        }
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-out_unblock_sillyrename:
+out_label:
        trace_nfs_lookup_exit(dir, dentry, flags, error);
        nfs4_label_free(label);
 out:
@@ -2014,7 +2013,8 @@ EXPORT_SYMBOL_GPL(nfs_link);
  * the rename.
  */
 int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-                     struct inode *new_dir, struct dentry *new_dentry)
+              struct inode *new_dir, struct dentry *new_dentry,
+              unsigned int flags)
 {
        struct inode *old_inode = d_inode(old_dentry);
        struct inode *new_inode = d_inode(new_dentry);
@@ -2022,6 +2022,9 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct rpc_task *task;
        int error = -EBUSY;
 
+       if (flags)
+               return -EINVAL;
+
        dfprintk(VFS, "NFS: rename(%pd2 -> %pd2, ct=%d)\n",
                 old_dentry, new_dentry,
                 d_count(new_dentry));
@@ -2253,21 +2256,37 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, st
        return NULL;
 }
 
-static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res)
+static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res, bool may_block)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_access_entry *cache;
-       int err = -ENOENT;
+       bool retry = true;
+       int err;
 
        spin_lock(&inode->i_lock);
-       if (nfsi->cache_validity & NFS_INO_INVALID_ACCESS)
-               goto out_zap;
-       cache = nfs_access_search_rbtree(inode, cred);
-       if (cache == NULL)
-               goto out;
-       if (!nfs_have_delegated_attributes(inode) &&
-           !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo))
-               goto out_stale;
+       for(;;) {
+               if (nfsi->cache_validity & NFS_INO_INVALID_ACCESS)
+                       goto out_zap;
+               cache = nfs_access_search_rbtree(inode, cred);
+               err = -ENOENT;
+               if (cache == NULL)
+                       goto out;
+               /* Found an entry, is our attribute cache valid? */
+               if (!nfs_attribute_cache_expired(inode) &&
+                   !(nfsi->cache_validity & NFS_INO_INVALID_ATTR))
+                       break;
+               err = -ECHILD;
+               if (!may_block)
+                       goto out;
+               if (!retry)
+                       goto out_zap;
+               spin_unlock(&inode->i_lock);
+               err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+               if (err)
+                       return err;
+               spin_lock(&inode->i_lock);
+               retry = false;
+       }
        res->jiffies = cache->jiffies;
        res->cred = cache->cred;
        res->mask = cache->mask;
@@ -2276,12 +2295,6 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str
 out:
        spin_unlock(&inode->i_lock);
        return err;
-out_stale:
-       rb_erase(&cache->rb_node, &nfsi->access_cache);
-       list_del(&cache->lru);
-       spin_unlock(&inode->i_lock);
-       nfs_access_free_entry(cache);
-       return -ENOENT;
 out_zap:
        spin_unlock(&inode->i_lock);
        nfs_access_zap_cache(inode);
@@ -2308,13 +2321,12 @@ static int nfs_access_get_cached_rcu(struct inode *inode, struct rpc_cred *cred,
                cache = NULL;
        if (cache == NULL)
                goto out;
-       if (!nfs_have_delegated_attributes(inode) &&
-           !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo))
+       err = nfs_revalidate_inode_rcu(NFS_SERVER(inode), inode);
+       if (err)
                goto out;
        res->jiffies = cache->jiffies;
        res->cred = cache->cred;
        res->mask = cache->mask;
-       err = 0;
 out:
        rcu_read_unlock();
        return err;
@@ -2403,18 +2415,19 @@ EXPORT_SYMBOL_GPL(nfs_access_set_mask);
 static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
 {
        struct nfs_access_entry cache;
+       bool may_block = (mask & MAY_NOT_BLOCK) == 0;
        int status;
 
        trace_nfs_access_enter(inode);
 
        status = nfs_access_get_cached_rcu(inode, cred, &cache);
        if (status != 0)
-               status = nfs_access_get_cached(inode, cred, &cache);
+               status = nfs_access_get_cached(inode, cred, &cache, may_block);
        if (status == 0)
                goto out_cached;
 
        status = -ECHILD;
-       if (mask & MAY_NOT_BLOCK)
+       if (!may_block)
                goto out;
 
        /* Be clever: ask server to check for all possible rights */
This page took 0.026629 seconds and 5 git commands to generate.