Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/ericvh/v9fs

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  [net/9p]: Introduce basic flow-control for VirtIO transport.
  9p: use the updated offset given by generic_write_checks
  [net/9p] Don't re-pin pages on retrying virtqueue_add_buf().
  [net/9p] Set the condition just before waking up.
  [net/9p] unconditional wake_up to proc waiting for space on VirtIO ring
  fs/9p: Add v9fs_dentry2v9ses
  fs/9p: Attach writeback_fid on first open with WR flag
  fs/9p: Open writeback fid in O_SYNC mode
  fs/9p: Use truncate_setsize instead of vmtruncate
  net/9p: Fix compile warning
  net/9p: Convert the in the 9p rpc call path to GFP_NOFS
  fs/9p: Fix race in initializing writeback fid
  • Loading branch information
Linus Torvalds committed Mar 22, 2011
2 parents 0adfc56 + 68da9ba commit ab70a1d
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 74 deletions.
4 changes: 2 additions & 2 deletions fs/9p/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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
Expand Down
19 changes: 15 additions & 4 deletions fs/9p/fid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -286,9 +286,11 @@ static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, uid_t uid)

struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
{
int err;
int err, flags;
struct p9_fid *fid;
struct v9fs_session_info *v9ses;

v9ses = v9fs_dentry2v9ses(dentry);
fid = v9fs_fid_clone_with_uid(dentry, 0);
if (IS_ERR(fid))
goto error_out;
Expand All @@ -297,8 +299,17 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
* dirty pages. We always request for the open fid in read-write
* mode so that a partial page write which result in page
* read can work.
*
* we don't have a tsyncfs operation for older version
* of protocol. So make sure the write back fid is
* opened in O_SYNC mode.
*/
err = p9_client_open(fid, O_RDWR);
if (!v9fs_proto_dotl(v9ses))
flags = O_RDWR | O_SYNC;
else
flags = O_RDWR;

err = p9_client_open(fid, flags);
if (err < 0) {
p9_client_clunk(fid);
fid = ERR_PTR(err);
Expand Down
6 changes: 6 additions & 0 deletions fs/9p/v9fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ struct v9fs_inode {
#endif
unsigned int cache_validity;
struct p9_fid *writeback_fid;
struct mutex v_mutex;
struct inode vfs_inode;
};

Expand Down Expand Up @@ -173,6 +174,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;
Expand Down
13 changes: 10 additions & 3 deletions fs/9p/vfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
29 changes: 19 additions & 10 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -993,19 +1002,19 @@ 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);

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);
Expand Down Expand Up @@ -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);
Expand Down
22 changes: 12 additions & 10 deletions fs/9p/vfs_inode_dotl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -448,26 +452,24 @@ 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);

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) {
Expand Down
2 changes: 1 addition & 1 deletion fs/9p/vfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,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) {
Expand Down
10 changes: 5 additions & 5 deletions net/9p/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)

req = &c->reqs[row][col];
if (!req->tc) {
req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS);
if (!req->wq) {
printk(KERN_ERR "Couldn't grow tag array\n");
return ERR_PTR(-ENOMEM);
Expand All @@ -233,17 +233,17 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
P9_TRANS_PREF_PAYLOAD_SEP) {
int alloc_msize = min(c->msize, 4096);
req->tc = kmalloc(sizeof(struct p9_fcall)+alloc_msize,
GFP_KERNEL);
GFP_NOFS);
req->tc->capacity = alloc_msize;
req->rc = kmalloc(sizeof(struct p9_fcall)+alloc_msize,
GFP_KERNEL);
GFP_NOFS);
req->rc->capacity = alloc_msize;
} else {
req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
GFP_KERNEL);
GFP_NOFS);
req->tc->capacity = c->msize;
req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
GFP_KERNEL);
GFP_NOFS);
req->rc->capacity = c->msize;
}
if ((!req->tc) || (!req->rc)) {
Expand Down
6 changes: 3 additions & 3 deletions net/9p/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
if (errcode)
break;

*sptr = kmalloc(len + 1, GFP_KERNEL);
*sptr = kmalloc(len + 1, GFP_NOFS);
if (*sptr == NULL) {
errcode = -EFAULT;
break;
Expand Down Expand Up @@ -273,7 +273,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
if (!errcode) {
*wnames =
kmalloc(sizeof(char *) * *nwname,
GFP_KERNEL);
GFP_NOFS);
if (!*wnames)
errcode = -ENOMEM;
}
Expand Down Expand Up @@ -317,7 +317,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
*wqids =
kmalloc(*nwqid *
sizeof(struct p9_qid),
GFP_KERNEL);
GFP_NOFS);
if (*wqids == NULL)
errcode = -ENOMEM;
}
Expand Down
10 changes: 5 additions & 5 deletions net/9p/trans_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ EXPORT_SYMBOL(p9_release_req_pages);
int
p9_nr_pages(struct p9_req_t *req)
{
int start_page, end_page;
start_page = (unsigned long long)req->tc->pubuf >> PAGE_SHIFT;
end_page = ((unsigned long long)req->tc->pubuf + req->tc->pbuf_size +
unsigned long start_page, end_page;
start_page = (unsigned long)req->tc->pubuf >> PAGE_SHIFT;
end_page = ((unsigned long)req->tc->pubuf + req->tc->pbuf_size +
PAGE_SIZE - 1) >> PAGE_SHIFT;
return end_page - start_page;
}
Expand All @@ -69,8 +69,8 @@ p9_payload_gup(struct p9_req_t *req, size_t *pdata_off, int *pdata_len,
*pdata_off = (size_t)req->tc->pubuf & (PAGE_SIZE-1);

if (*pdata_off)
first_page_bytes = min((PAGE_SIZE - *pdata_off),
req->tc->pbuf_size);
first_page_bytes = min(((size_t)PAGE_SIZE - *pdata_off),
req->tc->pbuf_size);

rpinfo = req->tc->private;
pdata_mapped_pages = get_user_pages_fast((unsigned long)req->tc->pubuf,
Expand Down
2 changes: 1 addition & 1 deletion net/9p/trans_fd.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ static void p9_read_work(struct work_struct *work)

if (m->req->rc == NULL) {
m->req->rc = kmalloc(sizeof(struct p9_fcall) +
m->client->msize, GFP_KERNEL);
m->client->msize, GFP_NOFS);
if (!m->req->rc) {
m->req = NULL;
err = -ENOMEM;
Expand Down
Loading

0 comments on commit ab70a1d

Please sign in to comment.