aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-28 12:25:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-28 12:25:11 -0400
commit90a2b69c14d0f0b6cbd124caf429ae9033f0615c (patch)
tree9aa18ac045eec9515ed225f900717e8a5f4fd8d6 /net
parente430426654c6a99fb1977bae71d4844e876c4a52 (diff)
parentf6ac55b6c156cebf750376dc08e06ffdade82717 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs: (28 commits) net/9p: Return error on read with NULL buffer 9p: Add datasync to client side TFSYNC/RFSYNC for dotl net/9p: Return error if we fail to encode protocol data fs/9p: Use generic_file_open with lookup_instantiate_filp fs/9p: Add missing iput in v9fs_vfs_lookup fs/9p: Use mknod 9p operation on create without open request net/9p: Add waitq to VirtIO transport. [net/9p]Serialize virtqueue operations to make VirtIO transport SMP safe. 9p: Implement TREADLINK operation for 9p2000.L 9p: Use V9FS_MAGIC in statfs 9p: Implement TGETLOCK 9p: Implement TLOCK [9p] Introduce client side TFSYNC/RFSYNC for dotl. [fs/9p] Add file_operations for cached mode in dotl protocol. fs/9p: Add access = client option to opt in acl evaluation. fs/9p: Implement create time inheritance fs/9p: Update ACL on chmod fs/9p: Implement setting posix acl fs/9p: Add xattr callbacks for POSIX ACL fs/9p: Implement POSIX ACL permission checking function ...
Diffstat (limited to 'net')
-rw-r--r--net/9p/client.c178
-rw-r--r--net/9p/protocol.c5
-rw-r--r--net/9p/trans_virtio.c76
3 files changed, 220 insertions, 39 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 83bf0541d66f..a848bca9fbff 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)
450 return err; 450 return err;
451 } 451 }
452 452
453 if (type == P9_RERROR) { 453 if (type == P9_RERROR || type == P9_RLERROR) {
454 int ecode; 454 int ecode;
455 char *ename;
456 455
457 err = p9pdu_readf(req->rc, c->proto_version, "s?d", 456 if (!p9_is_proto_dotl(c)) {
458 &ename, &ecode); 457 char *ename;
459 if (err) {
460 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
461 err);
462 return err;
463 }
464 458
465 if (p9_is_proto_dotu(c) || 459 err = p9pdu_readf(req->rc, c->proto_version, "s?d",
466 p9_is_proto_dotl(c)) 460 &ename, &ecode);
467 err = -ecode; 461 if (err)
462 goto out_err;
463
464 if (p9_is_proto_dotu(c))
465 err = -ecode;
466
467 if (!err || !IS_ERR_VALUE(err)) {
468 err = p9_errstr2errno(ename, strlen(ename));
469
470 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
468 471
469 if (!err || !IS_ERR_VALUE(err)) 472 kfree(ename);
470 err = p9_errstr2errno(ename, strlen(ename)); 473 }
474 } else {
475 err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
476 err = -ecode;
471 477
472 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); 478 P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
479 }
473 480
474 kfree(ename);
475 } else 481 } else
476 err = 0; 482 err = 0;
477 483
478 return err; 484 return err;
485
486out_err:
487 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
488
489 return err;
479} 490}
480 491
481/** 492/**
@@ -568,11 +579,14 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
568 va_start(ap, fmt); 579 va_start(ap, fmt);
569 err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); 580 err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
570 va_end(ap); 581 va_end(ap);
582 if (err)
583 goto reterr;
571 p9pdu_finalize(req->tc); 584 p9pdu_finalize(req->tc);
572 585
573 err = c->trans_mod->request(c, req); 586 err = c->trans_mod->request(c, req);
574 if (err < 0) { 587 if (err < 0) {
575 c->status = Disconnected; 588 if (err != -ERESTARTSYS)
589 c->status = Disconnected;
576 goto reterr; 590 goto reterr;
577 } 591 }
578 592
@@ -1151,12 +1165,44 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname)
1151} 1165}
1152EXPORT_SYMBOL(p9_client_link); 1166EXPORT_SYMBOL(p9_client_link);
1153 1167
1168int p9_client_fsync(struct p9_fid *fid, int datasync)
1169{
1170 int err;
1171 struct p9_client *clnt;
1172 struct p9_req_t *req;
1173
1174 P9_DPRINTK(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n",
1175 fid->fid, datasync);
1176 err = 0;
1177 clnt = fid->clnt;
1178
1179 req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync);
1180 if (IS_ERR(req)) {
1181 err = PTR_ERR(req);
1182 goto error;
1183 }
1184
1185 P9_DPRINTK(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid);
1186
1187 p9_free_req(clnt, req);
1188
1189error:
1190 return err;
1191}
1192EXPORT_SYMBOL(p9_client_fsync);
1193
1154int p9_client_clunk(struct p9_fid *fid) 1194int p9_client_clunk(struct p9_fid *fid)
1155{ 1195{
1156 int err; 1196 int err;
1157 struct p9_client *clnt; 1197 struct p9_client *clnt;
1158 struct p9_req_t *req; 1198 struct p9_req_t *req;
1159 1199
1200 if (!fid) {
1201 P9_EPRINTK(KERN_WARNING, "Trying to clunk with NULL fid\n");
1202 dump_stack();
1203 return 0;
1204 }
1205
1160 P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); 1206 P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
1161 err = 0; 1207 err = 0;
1162 clnt = fid->clnt; 1208 clnt = fid->clnt;
@@ -1240,16 +1286,13 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1240 1286
1241 if (data) { 1287 if (data) {
1242 memmove(data, dataptr, count); 1288 memmove(data, dataptr, count);
1243 } 1289 } else {
1244
1245 if (udata) {
1246 err = copy_to_user(udata, dataptr, count); 1290 err = copy_to_user(udata, dataptr, count);
1247 if (err) { 1291 if (err) {
1248 err = -EFAULT; 1292 err = -EFAULT;
1249 goto free_and_error; 1293 goto free_and_error;
1250 } 1294 }
1251 } 1295 }
1252
1253 p9_free_req(clnt, req); 1296 p9_free_req(clnt, req);
1254 return count; 1297 return count;
1255 1298
@@ -1761,3 +1804,96 @@ error:
1761 1804
1762} 1805}
1763EXPORT_SYMBOL(p9_client_mkdir_dotl); 1806EXPORT_SYMBOL(p9_client_mkdir_dotl);
1807
1808int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
1809{
1810 int err;
1811 struct p9_client *clnt;
1812 struct p9_req_t *req;
1813
1814 err = 0;
1815 clnt = fid->clnt;
1816 P9_DPRINTK(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d "
1817 "start %lld length %lld proc_id %d client_id %s\n",
1818 fid->fid, flock->type, flock->flags, flock->start,
1819 flock->length, flock->proc_id, flock->client_id);
1820
1821 req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type,
1822 flock->flags, flock->start, flock->length,
1823 flock->proc_id, flock->client_id);
1824
1825 if (IS_ERR(req))
1826 return PTR_ERR(req);
1827
1828 err = p9pdu_readf(req->rc, clnt->proto_version, "b", status);
1829 if (err) {
1830 p9pdu_dump(1, req->rc);
1831 goto error;
1832 }
1833 P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
1834error:
1835 p9_free_req(clnt, req);
1836 return err;
1837
1838}
1839EXPORT_SYMBOL(p9_client_lock_dotl);
1840
1841int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
1842{
1843 int err;
1844 struct p9_client *clnt;
1845 struct p9_req_t *req;
1846
1847 err = 0;
1848 clnt = fid->clnt;
1849 P9_DPRINTK(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld "
1850 "length %lld proc_id %d client_id %s\n", fid->fid, glock->type,
1851 glock->start, glock->length, glock->proc_id, glock->client_id);
1852
1853 req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, glock->type,
1854 glock->start, glock->length, glock->proc_id, glock->client_id);
1855
1856 if (IS_ERR(req))
1857 return PTR_ERR(req);
1858
1859 err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type,
1860 &glock->start, &glock->length, &glock->proc_id,
1861 &glock->client_id);
1862 if (err) {
1863 p9pdu_dump(1, req->rc);
1864 goto error;
1865 }
1866 P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
1867 "proc_id %d client_id %s\n", glock->type, glock->start,
1868 glock->length, glock->proc_id, glock->client_id);
1869error:
1870 p9_free_req(clnt, req);
1871 return err;
1872}
1873EXPORT_SYMBOL(p9_client_getlock_dotl);
1874
1875int p9_client_readlink(struct p9_fid *fid, char **target)
1876{
1877 int err;
1878 struct p9_client *clnt;
1879 struct p9_req_t *req;
1880
1881 err = 0;
1882 clnt = fid->clnt;
1883 P9_DPRINTK(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid);
1884
1885 req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid);
1886 if (IS_ERR(req))
1887 return PTR_ERR(req);
1888
1889 err = p9pdu_readf(req->rc, clnt->proto_version, "s", target);
1890 if (err) {
1891 p9pdu_dump(1, req->rc);
1892 goto error;
1893 }
1894 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
1895error:
1896 p9_free_req(clnt, req);
1897 return err;
1898}
1899EXPORT_SYMBOL(p9_client_readlink);
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index 3acd3afb20c8..45c15f491401 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -122,9 +122,8 @@ static size_t
122pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) 122pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
123{ 123{
124 size_t len = MIN(pdu->capacity - pdu->size, size); 124 size_t len = MIN(pdu->capacity - pdu->size, size);
125 int err = copy_from_user(&pdu->sdata[pdu->size], udata, len); 125 if (copy_from_user(&pdu->sdata[pdu->size], udata, len))
126 if (err) 126 len = 0;
127 printk(KERN_WARNING "pdu_write_u returning: %d\n", err);
128 127
129 pdu->size += len; 128 pdu->size += len;
130 return size - len; 129 return size - len;
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index b88515936e4b..c8f3f72ab20e 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -75,6 +75,8 @@ struct virtio_chan {
75 struct p9_client *client; 75 struct p9_client *client;
76 struct virtio_device *vdev; 76 struct virtio_device *vdev;
77 struct virtqueue *vq; 77 struct virtqueue *vq;
78 int ring_bufs_avail;
79 wait_queue_head_t *vc_wq;
78 80
79 /* Scatterlist: can be too big for stack. */ 81 /* Scatterlist: can be too big for stack. */
80 struct scatterlist sg[VIRTQUEUE_NUM]; 82 struct scatterlist sg[VIRTQUEUE_NUM];
@@ -134,16 +136,30 @@ static void req_done(struct virtqueue *vq)
134 struct p9_fcall *rc; 136 struct p9_fcall *rc;
135 unsigned int len; 137 unsigned int len;
136 struct p9_req_t *req; 138 struct p9_req_t *req;
139 unsigned long flags;
137 140
138 P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); 141 P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n");
139 142
140 while ((rc = virtqueue_get_buf(chan->vq, &len)) != NULL) { 143 do {
141 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); 144 spin_lock_irqsave(&chan->lock, flags);
142 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); 145 rc = virtqueue_get_buf(chan->vq, &len);
143 req = p9_tag_lookup(chan->client, rc->tag); 146
144 req->status = REQ_STATUS_RCVD; 147 if (rc != NULL) {
145 p9_client_cb(chan->client, req); 148 if (!chan->ring_bufs_avail) {
146 } 149 chan->ring_bufs_avail = 1;
150 wake_up(chan->vc_wq);
151 }
152 spin_unlock_irqrestore(&chan->lock, flags);
153 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
154 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n",
155 rc->tag);
156 req = p9_tag_lookup(chan->client, rc->tag);
157 req->status = REQ_STATUS_RCVD;
158 p9_client_cb(chan->client, req);
159 } else {
160 spin_unlock_irqrestore(&chan->lock, flags);
161 }
162 } while (rc != NULL);
147} 163}
148 164
149/** 165/**
@@ -199,23 +215,43 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
199 int in, out; 215 int in, out;
200 struct virtio_chan *chan = client->trans; 216 struct virtio_chan *chan = client->trans;
201 char *rdata = (char *)req->rc+sizeof(struct p9_fcall); 217 char *rdata = (char *)req->rc+sizeof(struct p9_fcall);
218 unsigned long flags;
219 int err;
202 220
203 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); 221 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n");
204 222
223req_retry:
224 req->status = REQ_STATUS_SENT;
225
226 spin_lock_irqsave(&chan->lock, flags);
205 out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, 227 out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata,
206 req->tc->size); 228 req->tc->size);
207 in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, 229 in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata,
208 client->msize); 230 client->msize);
209 231
210 req->status = REQ_STATUS_SENT; 232 err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
211 233 if (err < 0) {
212 if (virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc) < 0) { 234 if (err == -ENOSPC) {
213 P9_DPRINTK(P9_DEBUG_TRANS, 235 chan->ring_bufs_avail = 0;
214 "9p debug: virtio rpc add_buf returned failure"); 236 spin_unlock_irqrestore(&chan->lock, flags);
215 return -EIO; 237 err = wait_event_interruptible(*chan->vc_wq,
238 chan->ring_bufs_avail);
239 if (err == -ERESTARTSYS)
240 return err;
241
242 P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n");
243 goto req_retry;
244 } else {
245 spin_unlock_irqrestore(&chan->lock, flags);
246 P9_DPRINTK(P9_DEBUG_TRANS,
247 "9p debug: "
248 "virtio rpc add_buf returned failure");
249 return -EIO;
250 }
216 } 251 }
217 252
218 virtqueue_kick(chan->vq); 253 virtqueue_kick(chan->vq);
254 spin_unlock_irqrestore(&chan->lock, flags);
219 255
220 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); 256 P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n");
221 return 0; 257 return 0;
@@ -290,14 +326,23 @@ static int p9_virtio_probe(struct virtio_device *vdev)
290 chan->tag_len = tag_len; 326 chan->tag_len = tag_len;
291 err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); 327 err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
292 if (err) { 328 if (err) {
293 kfree(tag); 329 goto out_free_tag;
294 goto out_free_vq;
295 } 330 }
331 chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
332 if (!chan->vc_wq) {
333 err = -ENOMEM;
334 goto out_free_tag;
335 }
336 init_waitqueue_head(chan->vc_wq);
337 chan->ring_bufs_avail = 1;
338
296 mutex_lock(&virtio_9p_lock); 339 mutex_lock(&virtio_9p_lock);
297 list_add_tail(&chan->chan_list, &virtio_chan_list); 340 list_add_tail(&chan->chan_list, &virtio_chan_list);
298 mutex_unlock(&virtio_9p_lock); 341 mutex_unlock(&virtio_9p_lock);
299 return 0; 342 return 0;
300 343
344out_free_tag:
345 kfree(tag);
301out_free_vq: 346out_free_vq:
302 vdev->config->del_vqs(vdev); 347 vdev->config->del_vqs(vdev);
303 kfree(chan); 348 kfree(chan);
@@ -371,6 +416,7 @@ static void p9_virtio_remove(struct virtio_device *vdev)
371 mutex_unlock(&virtio_9p_lock); 416 mutex_unlock(&virtio_9p_lock);
372 sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); 417 sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
373 kfree(chan->tag); 418 kfree(chan->tag);
419 kfree(chan->vc_wq);
374 kfree(chan); 420 kfree(chan);
375 421
376} 422}