diff options
Diffstat (limited to 'fs/9p')
-rw-r--r-- | fs/9p/acl.c | 6 | ||||
-rw-r--r-- | fs/9p/fid.c | 4 | ||||
-rw-r--r-- | fs/9p/v9fs.h | 7 | ||||
-rw-r--r-- | fs/9p/vfs_dentry.c | 4 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 13 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 29 | ||||
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 24 | ||||
-rw-r--r-- | fs/9p/vfs_super.c | 82 |
8 files changed, 113 insertions, 56 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 51545529637..535ab6eccb1 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -262,7 +262,7 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, if (strcmp(name, "") != 0) return -EINVAL; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); /* * We allow set/get/list of acl when access=client is not specified */ @@ -312,7 +312,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, if (strcmp(name, "") != 0) return -EINVAL; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); /* * set the attribute on the remote. Without even looking at the * xattr value. We leave it to the server to validate @@ -323,7 +323,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { /* update the cached acl value */ diff --git a/fs/9p/fid.c b/fs/9p/fid.c index cd63e002d82..85b67ffa2a4 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -134,7 +134,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, struct v9fs_session_info *v9ses; struct p9_fid *fid, *old_fid = NULL; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); access = v9ses->flags & V9FS_ACCESS_MASK; fid = v9fs_fid_find(dentry, uid, any); if (fid) @@ -237,7 +237,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) int any, access; struct v9fs_session_info *v9ses; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); access = v9ses->flags & V9FS_ACCESS_MASK; switch (access) { case V9FS_ACCESS_SINGLE: diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index bd8496db135..e5ebedfc5ed 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -116,7 +116,6 @@ struct v9fs_session_info { struct list_head slist; /* list of sessions registered with v9fs */ struct backing_dev_info bdi; struct rw_semaphore rename_sem; - struct p9_fid *root_fid; /* Used for file system sync */ }; /* cache_validity flags */ @@ -130,6 +129,7 @@ struct v9fs_inode { #endif unsigned int cache_validity; struct p9_fid *writeback_fid; + struct mutex v_mutex; struct inode vfs_inode; }; @@ -173,6 +173,11 @@ static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) return (inode->i_sb->s_fs_info); } +static inline struct v9fs_session_info *v9fs_dentry2v9ses(struct dentry *dentry) +{ + return dentry->d_sb->s_fs_info; +} + static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses) { return v9ses->flags & V9FS_PROTO_2000U; diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index b6a3b9f7fe4..e022890c6f4 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -126,7 +126,9 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) retval = v9fs_refresh_inode_dotl(fid, inode); else retval = v9fs_refresh_inode(fid, inode); - if (retval <= 0) + if (retval == -ENOENT) + return 0; + if (retval < 0) return retval; } out_valid: diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 78bcb97c342..ffed55817f0 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -90,7 +90,9 @@ int v9fs_file_open(struct inode *inode, struct file *file) } file->private_data = fid; - if (v9ses->cache && !v9inode->writeback_fid) { + mutex_lock(&v9inode->v_mutex); + if (v9ses->cache && !v9inode->writeback_fid && + ((file->f_flags & O_ACCMODE) != O_RDONLY)) { /* * clone a fid and add it to writeback_fid * we do it during open time instead of @@ -101,10 +103,12 @@ int v9fs_file_open(struct inode *inode, struct file *file) fid = v9fs_writeback_fid(file->f_path.dentry); if (IS_ERR(fid)) { err = PTR_ERR(fid); + mutex_unlock(&v9inode->v_mutex); goto out_error; } v9inode->writeback_fid = (void *) fid; } + mutex_unlock(&v9inode->v_mutex); #ifdef CONFIG_9P_FSCACHE if (v9ses->cache) v9fs_cache_inode_set_cookie(inode, file); @@ -504,9 +508,12 @@ v9fs_file_write(struct file *filp, const char __user * data, if (!count) goto out; - return v9fs_file_write_internal(filp->f_path.dentry->d_inode, + retval = v9fs_file_write_internal(filp->f_path.dentry->d_inode, filp->private_data, - data, count, offset, 1); + data, count, &origin, 1); + /* update offset on successful write */ + if (retval > 0) + *offset = origin; out: return retval; } diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 8a2c232f708..7f6c6770319 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -221,6 +221,7 @@ struct inode *v9fs_alloc_inode(struct super_block *sb) #endif v9inode->writeback_fid = NULL; v9inode->cache_validity = 0; + mutex_init(&v9inode->v_mutex); return &v9inode->vfs_inode; } @@ -650,7 +651,9 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, /* if we are opening a file, assign the open fid to the file */ if (nd && nd->flags & LOOKUP_OPEN) { v9inode = V9FS_I(dentry->d_inode); - if (v9ses->cache && !v9inode->writeback_fid) { + mutex_lock(&v9inode->v_mutex); + if (v9ses->cache && !v9inode->writeback_fid && + ((flags & O_ACCMODE) != O_RDONLY)) { /* * clone a fid and add it to writeback_fid * we do it during open time instead of @@ -661,10 +664,12 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, inode_fid = v9fs_writeback_fid(dentry); if (IS_ERR(inode_fid)) { err = PTR_ERR(inode_fid); + mutex_unlock(&v9inode->v_mutex); goto error; } v9inode->writeback_fid = (void *) inode_fid; } + mutex_unlock(&v9inode->v_mutex); filp = lookup_instantiate_filp(nd, dentry, generic_file_open); if (IS_ERR(filp)) { err = PTR_ERR(filp); @@ -931,7 +936,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); err = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { generic_fillattr(dentry->d_inode, stat); return 0; @@ -967,8 +972,12 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) struct p9_wstat wstat; P9_DPRINTK(P9_DEBUG_VFS, "\n"); + retval = inode_change_ok(dentry->d_inode, iattr); + if (retval) + return retval; + retval = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); fid = v9fs_fid_lookup(dentry); if(IS_ERR(fid)) return PTR_ERR(fid); @@ -993,12 +1002,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) if (iattr->ia_valid & ATTR_GID) wstat.n_gid = iattr->ia_gid; } - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(dentry->d_inode)) { - retval = vmtruncate(dentry->d_inode, iattr->ia_size); - if (retval) - return retval; - } + /* Write all dirty data */ if (S_ISREG(dentry->d_inode->i_mode)) filemap_write_and_wait(dentry->d_inode->i_mapping); @@ -1006,6 +1010,11 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) retval = p9_client_wstat(fid, &wstat); if (retval < 0) return retval; + + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(dentry->d_inode)) + truncate_setsize(dentry->d_inode, iattr->ia_size); + v9fs_invalidate_inode_attr(dentry->d_inode); setattr_copy(dentry->d_inode, iattr); @@ -1130,7 +1139,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); retval = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); fid = v9fs_fid_lookup(dentry); if (IS_ERR(fid)) return PTR_ERR(fid); diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 67c138e94fe..82a7c38ddad 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -245,7 +245,9 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, v9fs_set_create_acl(dentry, dacl, pacl); v9inode = V9FS_I(inode); - if (v9ses->cache && !v9inode->writeback_fid) { + mutex_lock(&v9inode->v_mutex); + if (v9ses->cache && !v9inode->writeback_fid && + ((flags & O_ACCMODE) != O_RDONLY)) { /* * clone a fid and add it to writeback_fid * we do it during open time instead of @@ -256,10 +258,12 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, inode_fid = v9fs_writeback_fid(dentry); if (IS_ERR(inode_fid)) { err = PTR_ERR(inode_fid); + mutex_unlock(&v9inode->v_mutex); goto error; } v9inode->writeback_fid = (void *) inode_fid; } + mutex_unlock(&v9inode->v_mutex); /* Since we are opening a file, assign the open fid to the file */ filp = lookup_instantiate_filp(nd, dentry, generic_file_open); if (IS_ERR(filp)) { @@ -391,7 +395,7 @@ v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); err = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { generic_fillattr(dentry->d_inode, stat); return 0; @@ -448,17 +452,11 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; retval = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); fid = v9fs_fid_lookup(dentry); if (IS_ERR(fid)) return PTR_ERR(fid); - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(dentry->d_inode)) { - retval = vmtruncate(dentry->d_inode, iattr->ia_size); - if (retval) - return retval; - } /* Write all dirty data */ if (S_ISREG(dentry->d_inode->i_mode)) filemap_write_and_wait(dentry->d_inode->i_mapping); @@ -466,8 +464,12 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) retval = p9_client_setattr(fid, &p9attr); if (retval < 0) return retval; - v9fs_invalidate_inode_attr(dentry->d_inode); + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(dentry->d_inode)) + truncate_setsize(dentry->d_inode, iattr->ia_size); + + v9fs_invalidate_inode_attr(dentry->d_inode); setattr_copy(dentry->d_inode, iattr); mark_inode_dirty(dentry->d_inode); if (iattr->ia_valid & ATTR_MODE) { @@ -809,7 +811,7 @@ v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) fid = v9fs_fid_lookup(dentry); if (IS_ERR(fid)) { __putname(link); - link = ERR_PTR(PTR_ERR(fid)); + link = ERR_CAST(fid); goto ndset; } retval = p9_client_readlink(fid, &target); diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 09fd08d1606..feef6cdc1fd 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -154,6 +154,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, retval = PTR_ERR(inode); goto release_sb; } + root = d_alloc_root(inode); if (!root) { iput(inode); @@ -185,21 +186,10 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, p9stat_free(st); kfree(st); } - v9fs_fid_add(root, fid); retval = v9fs_get_acl(inode, fid); if (retval) goto release_sb; - /* - * Add the root fid to session info. This is used - * for file system sync. We want a cloned fid here - * so that we can do a sync_filesystem after a - * shrink_dcache_for_umount - */ - v9ses->root_fid = v9fs_fid_clone(root); - if (IS_ERR(v9ses->root_fid)) { - retval = PTR_ERR(v9ses->root_fid); - goto release_sb; - } + v9fs_fid_add(root, fid); P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); return dget(sb->s_root); @@ -210,11 +200,15 @@ close_session: v9fs_session_close(v9ses); kfree(v9ses); return ERR_PTR(retval); + release_sb: /* - * we will do the session_close and root dentry - * release in the below call. + * we will do the session_close and root dentry release + * in the below call. But we need to clunk fid, because we haven't + * attached the fid to dentry so it won't get clunked + * automatically. */ + p9_client_clunk(fid); deactivate_locked_super(sb); return ERR_PTR(retval); } @@ -232,7 +226,7 @@ static void v9fs_kill_super(struct super_block *s) P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); kill_anon_super(s); - p9_client_clunk(v9ses->root_fid); + v9fs_session_cancel(v9ses); v9fs_session_close(v9ses); kfree(v9ses); @@ -262,7 +256,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) goto done; } - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); if (v9fs_proto_dotl(v9ses)) { res = p9_client_statfs(fid, &rs); if (res == 0) { @@ -285,14 +279,6 @@ done: return res; } -static int v9fs_sync_fs(struct super_block *sb, int wait) -{ - struct v9fs_session_info *v9ses = sb->s_fs_info; - - P9_DPRINTK(P9_DEBUG_VFS, "v9fs_sync_fs: super_block %p\n", sb); - return p9_client_sync_fs(v9ses->root_fid); -} - static int v9fs_drop_inode(struct inode *inode) { struct v9fs_session_info *v9ses; @@ -307,6 +293,51 @@ static int v9fs_drop_inode(struct inode *inode) return 1; } +static int v9fs_write_inode(struct inode *inode, + struct writeback_control *wbc) +{ + int ret; + struct p9_wstat wstat; + struct v9fs_inode *v9inode; + /* + * send an fsync request to server irrespective of + * wbc->sync_mode. + */ + P9_DPRINTK(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); + v9inode = V9FS_I(inode); + if (!v9inode->writeback_fid) + return 0; + v9fs_blank_wstat(&wstat); + + ret = p9_client_wstat(v9inode->writeback_fid, &wstat); + if (ret < 0) { + __mark_inode_dirty(inode, I_DIRTY_DATASYNC); + return ret; + } + return 0; +} + +static int v9fs_write_inode_dotl(struct inode *inode, + struct writeback_control *wbc) +{ + int ret; + struct v9fs_inode *v9inode; + /* + * send an fsync request to server irrespective of + * wbc->sync_mode. + */ + P9_DPRINTK(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); + v9inode = V9FS_I(inode); + if (!v9inode->writeback_fid) + return 0; + ret = p9_client_fsync(v9inode->writeback_fid, 0); + if (ret < 0) { + __mark_inode_dirty(inode, I_DIRTY_DATASYNC); + return ret; + } + return 0; +} + static const struct super_operations v9fs_super_ops = { .alloc_inode = v9fs_alloc_inode, .destroy_inode = v9fs_destroy_inode, @@ -314,17 +345,18 @@ static const struct super_operations v9fs_super_ops = { .evict_inode = v9fs_evict_inode, .show_options = generic_show_options, .umount_begin = v9fs_umount_begin, + .write_inode = v9fs_write_inode, }; static const struct super_operations v9fs_super_ops_dotl = { .alloc_inode = v9fs_alloc_inode, .destroy_inode = v9fs_destroy_inode, - .sync_fs = v9fs_sync_fs, .statfs = v9fs_statfs, .drop_inode = v9fs_drop_inode, .evict_inode = v9fs_evict_inode, .show_options = generic_show_options, .umount_begin = v9fs_umount_begin, + .write_inode = v9fs_write_inode_dotl, }; struct file_system_type v9fs_fs_type = { |