-int obdfs_unlink(struct inode * dir, struct dentry *dentry)
-{
- int retval;
- struct inode * inode;
- struct page *page;
- struct ext2_dir_entry_2 * de;
-
- ENTRY;
-
- retval = -ENOENT;
- page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED);
- if (!page)
- goto end_unlink;
-
- inode = dentry->d_inode;
- DQUOT_INIT(inode);
-
- retval = -EIO;
- if (le32_to_cpu(de->inode) != inode->i_ino)
- goto end_unlink;
-
- if (!inode->i_nlink) {
- ext2_warning (inode->i_sb, "ext2_unlink",
- "Deleting nonexistent file (%lu), %d",
- inode->i_ino, inode->i_nlink);
- inode->i_nlink = 1;
- }
- retval = obdfs_delete_entry (de, page);
- if (retval)
- goto end_unlink;
- dir->i_version = ++event;
- retval = obdfs_do_writepage(page, IS_SYNC(dir));
- /* XXX handle err? */
- obd_unlock_page(page);
-
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
- mark_inode_dirty(dir);
- inode->i_nlink--;
- mark_inode_dirty(inode);
- inode->i_ctime = dir->i_ctime;
- d_delete(dentry); /* This also frees the inode */
-
-end_unlink:
- if (page)
- page_cache_release(page);
- EXIT;
- return retval;
-} /* obdfs_unlink */
-
-int obdfs_symlink (struct inode * dir, struct dentry *dentry,
- const char * symname)
-{
- struct inode * inode;
- struct ext2_dir_entry_2 * de;
- struct obdfs_inode_info *oinfo;
- struct page* page = NULL, * name_page = NULL;
- char * link;
- int l, err;
-
- ENTRY;
- err = -ENAMETOOLONG;
- l = strlen(symname)+1;
- if (l > PAGE_SIZE) {
- EXIT;
- goto out;
- }
-
- inode = obdfs_new_inode(dir, S_IFLNK);
- if ( IS_ERR(inode) ) {
- EXIT;
- goto out;
- }
-
- inode->i_mode = S_IFLNK | S_IRWXUGO;
- oinfo = obdfs_i2info(inode);
-
- if (l >= sizeof(oinfo->oi_inline)) {
- CDEBUG(D_INFO, "l=%d, normal symlink\n", l);
- inode->i_op = &obdfs_symlink_inode_operations;
-
- name_page = obdfs_getpage(inode, 0, 1, LOCKED);
- if (!name_page) {
- EXIT;
- err = -ENOMEM;
- goto out_no_entry;
- }
- link = (char *)page_address(name_page);
- } else {
- CDEBUG(D_INFO, "l=%d, fast symlink\n", l);
- inode->i_op = &obdfs_fast_symlink_inode_operations;
- link = oinfo->oi_inline;
- oinfo->oi_flags |= OBD_FL_INLINEDATA;
- }
- memcpy(link, symname, l);
- if (name_page) {
- err = obdfs_do_writepage(name_page, IS_SYNC(inode));
- /* PDEBUG(name_page, "symlink"); */
- obd_unlock_page(name_page);
- page_cache_release(name_page);
- if (err) {
- EXIT;
- goto out_no_entry;
- }
- }
- inode->i_size = l-1;
- mark_inode_dirty(inode);
-
- page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len,
- &de, &err);
- if (!page)
- goto out_no_entry;
- de->inode = cpu_to_le32(inode->i_ino);
- ext2_set_de_type(dir->i_sb, de, S_IFLNK);
- dir->i_version = ++event;
- err = obdfs_do_writepage(page, IS_SYNC(dir));
- obd_unlock_page(page);
-
- d_instantiate(dentry, inode);
-out:
- EXIT;
- return err;
-
-out_no_entry:
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput (inode);
- goto out;
-} /* obdfs_symlink */
-
-int obdfs_link (struct dentry * old_dentry,
- struct inode * dir, struct dentry *dentry)
-{
- struct inode *inode = old_dentry->d_inode;
- struct ext2_dir_entry_2 * de;
- struct page *page;
- int err;
-
- ENTRY;
-
- if (S_ISDIR(inode->i_mode))
- return -EPERM;
-
- if (inode->i_nlink >= EXT2_LINK_MAX)
- return -EMLINK;
-
- page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
- if (!page)
- return err;
-
- de->inode = cpu_to_le32(inode->i_ino);
- ext2_set_de_type(dir->i_sb, de, inode->i_mode);
- dir->i_version = ++event;
-
- err = obdfs_do_writepage(page, IS_SYNC(dir));
- obd_unlock_page(page);