return err;
 }
 
-static struct page * dir_get_page(struct inode *dir, unsigned long n)
+static void *dir_get_page(struct inode *dir, unsigned long n, struct page **p)
 {
        struct address_space *mapping = dir->i_mapping;
        struct page *page = read_mapping_page(mapping, n, NULL);
-       if (!IS_ERR(page))
-               kmap(page);
-       return page;
+       if (IS_ERR(page))
+               return ERR_CAST(page);
+       kmap(page);
+       *p = page;
+       return page_address(page);
 }
 
 static int sysv_readdir(struct file *file, struct dir_context *ctx)
        for ( ; n < npages; n++, offset = 0) {
                char *kaddr, *limit;
                struct sysv_dir_entry *de;
-               struct page *page = dir_get_page(inode, n);
+               struct page *page;
 
-               if (IS_ERR(page))
+               kaddr = dir_get_page(inode, n, &page);
+               if (IS_ERR(kaddr))
                        continue;
-               kaddr = (char *)page_address(page);
                de = (struct sysv_dir_entry *)(kaddr+offset);
                limit = kaddr + PAGE_SIZE - SYSV_DIRSIZE;
                for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) {
        n = start;
 
        do {
-               char *kaddr;
-               page = dir_get_page(dir, n);
-               if (!IS_ERR(page)) {
-                       kaddr = (char*)page_address(page);
-                       de = (struct sysv_dir_entry *) kaddr;
+               char *kaddr = dir_get_page(dir, n, &page);
+
+               if (!IS_ERR(kaddr)) {
+                       de = (struct sysv_dir_entry *)kaddr;
                        kaddr += PAGE_SIZE - SYSV_DIRSIZE;
                        for ( ; (char *) de <= kaddr ; de++) {
                                if (!de->inode)
 
        /* We take care of directory expansion in the same loop */
        for (n = 0; n <= npages; n++) {
-               page = dir_get_page(dir, n);
-               err = PTR_ERR(page);
-               if (IS_ERR(page))
-                       goto out;
-               kaddr = (char*)page_address(page);
+               kaddr = dir_get_page(dir, n, &page);
+               if (IS_ERR(kaddr))
+                       return PTR_ERR(kaddr);
                de = (struct sysv_dir_entry *)kaddr;
                kaddr += PAGE_SIZE - SYSV_DIRSIZE;
                while ((char *)de <= kaddr) {
        err = sysv_handle_dirsync(dir);
 out_page:
        dir_put_page(page);
-out:
        return err;
 out_unlock:
        unlock_page(page);
        for (i = 0; i < npages; i++) {
                char *kaddr;
                struct sysv_dir_entry * de;
-               page = dir_get_page(inode, i);
 
-               if (IS_ERR(page))
+               kaddr = dir_get_page(inode, i, &page);
+               if (IS_ERR(kaddr))
                        continue;
 
-               kaddr = (char *)page_address(page);
                de = (struct sysv_dir_entry *)kaddr;
                kaddr += PAGE_SIZE-SYSV_DIRSIZE;
 
        sysv_handle_dirsync(inode);
 }
 
-struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct page **p)
+struct sysv_dir_entry *sysv_dotdot(struct inode *dir, struct page **p)
 {
-       struct page *page = dir_get_page(dir, 0);
-       struct sysv_dir_entry *de = NULL;
+       struct sysv_dir_entry *de = dir_get_page(dir, 0, p);
 
-       if (!IS_ERR(page)) {
-               de = (struct sysv_dir_entry*) page_address(page) + 1;
-               *p = page;
-       }
-       return de;
+       if (IS_ERR(de))
+               return NULL;
+       /* ".." is the second directory entry */
+       return de + 1;
 }
 
 ino_t sysv_inode_by_name(struct dentry *dentry)