[PATCH] NFS: fix minor bug in new NFS symlink code
[powerpc.git] / fs / nfs / dir.c
index b483e5d..c86a1ea 100644 (file)
@@ -203,8 +203,10 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
         * Note: assumes we have exclusive access to this mapping either
         *       through inode->i_mutex or some other mechanism.
         */
-       if (page->index == 0)
-               invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1);
+       if (page->index == 0 && invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1) < 0) {
+               /* Should never happen */
+               nfs_zap_mapping(inode, inode->i_mapping);
+       }
        unlock_page(page);
        return 0;
  error:
@@ -843,7 +845,7 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
        nfs_inode_return_delegation(inode);
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
                lock_kernel();
-               inode->i_nlink--;
+               drop_nlink(inode);
                nfs_complete_unlink(dentry);
                unlock_kernel();
        }
@@ -904,9 +906,15 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
 
        lock_kernel();
 
-       /* If we're doing an exclusive create, optimize away the lookup */
-       if (nfs_is_exclusive_create(dir, nd))
-               goto no_entry;
+       /*
+        * If we're doing an exclusive create, optimize away the lookup
+        * but don't hash the dentry.
+        */
+       if (nfs_is_exclusive_create(dir, nd)) {
+               d_instantiate(dentry, NULL);
+               res = NULL;
+               goto out_unlock;
+       }
 
        error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
        if (error == -ENOENT)
@@ -1161,6 +1169,8 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
        if (IS_ERR(inode))
                return error;
        d_instantiate(dentry, inode);
+       if (d_unhashed(dentry))
+               d_rehash(dentry);
        return 0;
 }
 
@@ -1278,7 +1288,7 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
        error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
        /* Ensure the VFS deletes this inode */
        if (error == 0 && dentry->d_inode != NULL)
-               dentry->d_inode->i_nlink = 0;
+               clear_nlink(dentry->d_inode);
        nfs_end_data_update(dir);
        unlock_kernel();
 
@@ -1393,7 +1403,7 @@ static int nfs_safe_remove(struct dentry *dentry)
                error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
                /* The VFS may want to delete this inode */
                if (error == 0)
-                       inode->i_nlink--;
+                       drop_nlink(inode);
                nfs_mark_for_revalidate(inode);
                nfs_end_data_update(inode);
        } else
@@ -1464,10 +1474,6 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
        char *kaddr;
        struct iattr attr;
        unsigned int pathlen = strlen(symname);
-       struct qstr qsymname = {
-               .name   = symname,
-               .len    = pathlen,
-       };
        int error;
 
        dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
@@ -1493,10 +1499,8 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
                memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
        kunmap_atomic(kaddr, KM_USER0);
 
-       /* XXX: eventually this will pass in {page, pathlen},
-        *      instead of qsymname; need XDR changes for that */
        nfs_begin_data_update(dir);
-       error = NFS_PROTO(dir)->symlink(dir, dentry, &qsymname, &attr);
+       error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
        nfs_end_data_update(dir);
        if (error != 0) {
                dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n",
@@ -1515,8 +1519,8 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
        pagevec_init(&lru_pvec, 0);
        if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0,
                                                        GFP_KERNEL)) {
-               if (!pagevec_add(&lru_pvec, page))
-                       __pagevec_lru_add(&lru_pvec);
+               pagevec_add(&lru_pvec, page);
+               pagevec_lru_add(&lru_pvec);
                SetPageUptodate(page);
                unlock_page(page);
        } else
@@ -1637,7 +1641,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        goto out;
                }
        } else
-               new_inode->i_nlink--;
+               drop_nlink(new_inode);
 
 go_ahead:
        /*
@@ -1667,8 +1671,7 @@ out:
        if (rehash)
                d_rehash(rehash);
        if (!error) {
-               if (!S_ISDIR(old_inode->i_mode))
-                       d_move(old_dentry, new_dentry);
+               d_move(old_dentry, new_dentry);
                nfs_renew_times(new_dentry);
                nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir));
        }