diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-10-01 11:10:56 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-10-01 11:10:56 +1000 |
commit | faa542fdf347410e47ed608b04668e26f9da771d (patch) | |
tree | 7d73ce54264e9198fc4c6f87be800994aaac8809 | |
parent | bbc33dd2d467032276ec25e940b16dcf8472d7bd (diff) | |
parent | 95bc923391549c5e54b502998c316e8c1f4071f5 (diff) |
Merge remote branch 'v9fs/for-next'
-rw-r--r-- | fs/9p/vfs_addr.c | 30 | ||||
-rw-r--r-- | fs/9p/vfs_dir.c | 3 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 29 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 15 | ||||
-rw-r--r-- | include/net/9p/9p.h | 4 | ||||
-rw-r--r-- | net/9p/client.c | 49 |
6 files changed, 90 insertions, 40 deletions
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 90e38449f4b3..b7f2a8e3863e 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -154,10 +154,40 @@ static int v9fs_launder_page(struct page *page) return 0; } +/** + * v9fs_direct_IO - 9P address space operation for direct I/O + * @rw: direction (read or write) + * @iocb: target I/O control block + * @iov: array of vectors that define I/O buffer + * @pos: offset in file to begin the operation + * @nr_segs: size of iovec array + * + * The presence of v9fs_direct_IO() in the address space ops vector + * allowes open() O_DIRECT flags which would have failed otherwise. + * + * In the non-cached mode, we shunt off direct read and write requests before + * the VFS gets them, so this method should never be called. + * + * Direct IO is not 'yet' supported in the cached mode. Hence when + * this routine is called through generic_file_aio_read(), the read/write fails + * with an error. + * + */ +ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, + loff_t pos, unsigned long nr_segs) +{ + P9_DPRINTK(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%s) " + "off/no(%lld/%lu) EINVAL\n", + iocb->ki_filp->f_path.dentry->d_name.name, + (long long) pos, nr_segs); + + return -EINVAL; +} const struct address_space_operations v9fs_addr_operations = { .readpage = v9fs_vfs_readpage, .readpages = v9fs_vfs_readpages, .releasepage = v9fs_release_page, .invalidatepage = v9fs_invalidate_page, .launder_page = v9fs_launder_page, + .direct_IO = v9fs_direct_IO, }; diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 899f168fd19c..170f5bb8ebe0 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -242,7 +242,8 @@ static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent, while (rdir->head < rdir->tail) { err = p9dirent_read(rdir->buf + rdir->head, - buflen - rdir->head, &curdirent, + rdir->tail - rdir->head, + &curdirent, fid->clnt->proto_version); if (err < 0) { P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index e97c92bd6f16..f455c45a8c5f 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -219,7 +219,9 @@ static ssize_t v9fs_file_write(struct file *filp, const char __user * data, size_t count, loff_t * offset) { - int n, rsize, total = 0; + ssize_t retval; + size_t total = 0; + int n; struct p9_fid *fid; struct p9_client *clnt; struct inode *inode = filp->f_path.dentry->d_inode; @@ -232,14 +234,19 @@ v9fs_file_write(struct file *filp, const char __user * data, fid = filp->private_data; clnt = fid->clnt; - rsize = fid->iounit ? fid->iounit : clnt->msize - P9_IOHDRSZ; + retval = generic_write_checks(filp, &origin, &count, 0); + if (retval) + goto out; - do { - if (count < rsize) - rsize = count; + retval = -EINVAL; + if ((ssize_t) count < 0) + goto out; + retval = 0; + if (!count) + goto out; - n = p9_client_write(fid, NULL, data+total, origin+total, - rsize); + do { + n = p9_client_write(fid, NULL, data+total, origin+total, count); if (n <= 0) break; count -= n; @@ -258,9 +265,11 @@ v9fs_file_write(struct file *filp, const char __user * data, } if (n < 0) - return n; - - return total; + retval = n; + else + retval = total; +out: + return retval; } static int v9fs_file_fsync(struct file *filp, int datasync) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 9e670d527646..bfc8d07e0dc9 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -876,6 +876,8 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, v9ses = v9fs_inode2v9ses(dir); mode |= S_IFDIR; + if (dir->i_mode & S_ISGID) + mode |= S_ISGID; dir_dentry = v9fs_dentry_from_dir_inode(dir); dfid = v9fs_fid_lookup(dir_dentry); if (IS_ERR(dfid)) { @@ -886,10 +888,6 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, } gid = v9fs_get_fsgid_for_create(dir); - if (gid < 0) { - P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n"); - goto error; - } name = (char *) dentry->d_name.name; err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); @@ -1616,11 +1614,6 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, gid = v9fs_get_fsgid_for_create(dir); - if (gid < 0) { - P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_egid failed %d\n", gid); - goto error; - } - /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); @@ -1884,10 +1877,6 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, } gid = v9fs_get_fsgid_for_create(dir); - if (gid < 0) { - P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n"); - goto error; - } name = (char *) dentry->d_name.name; diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index a8de812ccbc8..a4a1b043a8c4 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -86,6 +86,8 @@ do { \ /** * enum p9_msg_t - 9P message types + * @P9_TLERROR: not used + * @P9_RLERROR: response for any failed request for 9P2000.L * @P9_TSTATFS: file system status request * @P9_RSTATFS: file system status response * @P9_TSYMLINK: make symlink request @@ -137,6 +139,8 @@ do { \ */ enum p9_msg_t { + P9_TLERROR = 6, + P9_RLERROR, P9_TSTATFS = 8, P9_RSTATFS, P9_TLOPEN = 12, diff --git a/net/9p/client.c b/net/9p/client.c index 9eb72505308f..208efce8d40f 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -450,32 +450,43 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) return err; } - if (type == P9_RERROR) { + if (type == P9_RERROR || type == P9_RLERROR) { int ecode; - char *ename; - err = p9pdu_readf(req->rc, c->proto_version, "s?d", - &ename, &ecode); - if (err) { - P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", - err); - return err; - } + if (!p9_is_proto_dotl(c)) { + char *ename; - if (p9_is_proto_dotu(c) || - p9_is_proto_dotl(c)) - err = -ecode; + err = p9pdu_readf(req->rc, c->proto_version, "s?d", + &ename, &ecode); + if (err) + goto out_err; - if (!err || !IS_ERR_VALUE(err)) - err = p9_errstr2errno(ename, strlen(ename)); + if (p9_is_proto_dotu(c)) + err = -ecode; + + if (!err || !IS_ERR_VALUE(err)) { + err = p9_errstr2errno(ename, strlen(ename)); + + P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); + + kfree(ename); + } + } else { + err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); + err = -ecode; - P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); + P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); + } - kfree(ename); } else err = 0; return err; + +out_err: + P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); + + return err; } /** @@ -1206,6 +1217,12 @@ int p9_client_clunk(struct p9_fid *fid) struct p9_client *clnt; struct p9_req_t *req; + if (!fid) { + P9_EPRINTK(KERN_WARNING, "Trying to clunk with NULL fid\n"); + dump_stack(); + return 0; + } + P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); err = 0; clnt = fid->clnt; |