diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r-- | fs/9p/vfs_inode.c | 91 |
1 files changed, 56 insertions, 35 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c72e20c..bf1df72 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -278,10 +278,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses, case S_IFSOCK: if (v9fs_proto_dotl(v9ses)) { inode->i_op = &v9fs_file_inode_operations_dotl; - inode->i_fop = &v9fs_file_operations_dotl; } else if (v9fs_proto_dotu(v9ses)) { inode->i_op = &v9fs_file_inode_operations; - inode->i_fop = &v9fs_file_operations; } else { P9_DPRINTK(P9_DEBUG_ERROR, "special files without extended mode\n"); @@ -529,8 +527,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, unlock_new_inode(inode); return inode; error: - unlock_new_inode(inode); - iput(inode); + iget_failed(inode); return ERR_PTR(retval); } @@ -553,40 +550,66 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, } /** + * v9fs_at_to_dotl_flags- convert Linux specific AT flags to + * plan 9 AT flag. + * @flags: flags to convert + */ +static int v9fs_at_to_dotl_flags(int flags) +{ + int rflags = 0; + if (flags & AT_REMOVEDIR) + rflags |= P9_DOTL_AT_REMOVEDIR; + return rflags; +} + +/** * v9fs_remove - helper function to remove files and directories * @dir: directory inode that is being deleted - * @file: dentry that is being deleted + * @dentry: dentry that is being deleted * @rmdir: removing a directory * */ -static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) +static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags) { - int retval; - struct p9_fid *v9fid; - struct inode *file_inode; - - P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, - rmdir); + struct inode *inode; + int retval = -EOPNOTSUPP; + struct p9_fid *v9fid, *dfid; + struct v9fs_session_info *v9ses; - file_inode = file->d_inode; - v9fid = v9fs_fid_clone(file); - if (IS_ERR(v9fid)) - return PTR_ERR(v9fid); + P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n", + dir, dentry, flags); - retval = p9_client_remove(v9fid); + v9ses = v9fs_inode2v9ses(dir); + inode = dentry->d_inode; + dfid = v9fs_fid_lookup(dentry->d_parent); + if (IS_ERR(dfid)) { + retval = PTR_ERR(dfid); + P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", retval); + return retval; + } + if (v9fs_proto_dotl(v9ses)) + retval = p9_client_unlinkat(dfid, dentry->d_name.name, + v9fs_at_to_dotl_flags(flags)); + if (retval == -EOPNOTSUPP) { + /* Try the one based on path */ + v9fid = v9fs_fid_clone(dentry); + if (IS_ERR(v9fid)) + return PTR_ERR(v9fid); + retval = p9_client_remove(v9fid); + } if (!retval) { /* * directories on unlink should have zero * link count */ - if (rmdir) { - clear_nlink(file_inode); + if (flags & AT_REMOVEDIR) { + clear_nlink(inode); drop_nlink(dir); } else - drop_nlink(file_inode); + drop_nlink(inode); - v9fs_invalidate_inode_attr(file_inode); + v9fs_invalidate_inode_attr(inode); v9fs_invalidate_inode_attr(dir); } return retval; @@ -694,8 +717,8 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, fid = NULL; v9ses = v9fs_inode2v9ses(dir); perm = unixmode2p9mode(v9ses, mode); - if (nd && nd->flags & LOOKUP_OPEN) - flags = nd->intent.open.flags - 1; + if (nd) + flags = nd->intent.open.flags; else flags = O_RDWR; @@ -710,7 +733,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, v9fs_invalidate_inode_attr(dir); /* if we are opening a file, assign the open fid to the file */ - if (nd && nd->flags & LOOKUP_OPEN) { + if (nd) { v9inode = V9FS_I(dentry->d_inode); mutex_lock(&v9inode->v_mutex); if (v9ses->cache && !v9inode->writeback_fid && @@ -889,7 +912,7 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d) int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) { - return v9fs_remove(i, d, 1); + return v9fs_remove(i, d, AT_REMOVEDIR); } /** @@ -937,9 +960,12 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, down_write(&v9ses->rename_sem); if (v9fs_proto_dotl(v9ses)) { - retval = p9_client_rename(oldfid, newdirfid, - (char *) new_dentry->d_name.name); - if (retval != -ENOSYS) + retval = p9_client_renameat(olddirfid, old_dentry->d_name.name, + newdirfid, new_dentry->d_name.name); + if (retval == -EOPNOTSUPP) + retval = p9_client_rename(oldfid, newdirfid, + new_dentry->d_name.name); + if (retval != -EOPNOTSUPP) goto clunk_newdir; } if (old_dentry->d_parent != new_dentry->d_parent) { @@ -964,11 +990,6 @@ clunk_newdir: clear_nlink(new_inode); else drop_nlink(new_inode); - /* - * Work around vfs rename rehash bug with - * FS_RENAME_DOES_D_MOVE - */ - v9fs_invalidate_inode_attr(new_inode); } if (S_ISDIR(old_inode->i_mode)) { if (!new_inode) @@ -1116,7 +1137,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, struct v9fs_session_info *v9ses = sb->s_fs_info; struct v9fs_inode *v9inode = V9FS_I(inode); - inode->i_nlink = 1; + set_nlink(inode, 1); inode->i_atime.tv_sec = stat->atime; inode->i_mtime.tv_sec = stat->mtime; @@ -1142,7 +1163,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, /* HARDLINKCOUNT %u */ sscanf(ext, "%13s %u", tag_name, &i_nlink); if (!strncmp(tag_name, "HARDLINKCOUNT", 13)) - inode->i_nlink = i_nlink; + set_nlink(inode, i_nlink); } } mode = stat->mode & S_IALLUGO; |