return err;
}
+
+/* XXX sort this out -- why is our readpage re-reading the page? */
+static int obdfs_page_symlink(struct inode *inode, const char *symname, int len)
+{
+ struct address_space *mapping = inode->i_mapping;
+ struct page *page = grab_cache_page(mapping, 0);
+ int err = -ENOMEM;
+ char *kaddr;
+
+ if (!page)
+ goto fail;
+ err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
+ if (err)
+ goto fail_map;
+ kaddr = page_address(page);
+ memcpy(kaddr, symname, len-1);
+ mapping->a_ops->commit_write(NULL, page, 0, len-1);
+#if 0
+ /*
+ * Notice that we are _not_ going to block here - end of page is
+ * unmapped, so this will only try to map the rest of page, see
+ * that it is unmapped (typically even will not look into inode -
+ * ->i_size will be enough for everything) and zero it out.
+ * OTOH it's obviously correct and should make the page up-to-date.
+ */
+ err = mapping->a_ops->readpage(NULL, page);
+ wait_on_page(page);
+#endif
+ obd_unlock_page(page);
+ page_cache_release(page);
+ if (err < 0)
+ goto fail;
+ mark_inode_dirty(inode);
+ return 0;
+fail_map:
+ UnlockPage(page);
+ page_cache_release(page);
+fail:
+ return err;
+}
+
+
static int obdfs_symlink (struct inode * dir, struct dentry * dentry,
const char * symname)
{
unsigned l = strlen(symname)+1;
struct inode * inode;
struct obdfs_inode_info *oinfo;
- oinfo = obdfs_i2info(inode);
if (l > sb->s_blocksize)
goto out;
if (IS_ERR(inode))
goto out;
+ oinfo = obdfs_i2info(inode);
if (l >= sizeof(oinfo->oi_inline)) {
/* slow symlink */
- inode->i_op = &obdfs_symlink_inode_operations;
+ inode->i_op = &page_symlink_inode_operations;
inode->i_mapping->a_ops = &obdfs_aops;
- err = block_symlink(inode, symname, l);
+ printk("-----> calling block symlink len %d\n", l);
+ err = obdfs_page_symlink(inode, symname, l);
+ printk("-----> calling block err %d\n", err);
if (err)
goto out_fail;
} else {
/* fast symlink */
inode->i_op = &obdfs_fast_symlink_inode_operations;
- memcpy((char*)&inode->u.ext2_i.i_data,symname,l);
+ memcpy(oinfo->oi_inline, symname, l);
inode->i_size = l-1;
}
mark_inode_dirty(inode);