|
@@ -72,23 +72,22 @@ inline int p9_is_proto_dotu(struct p9_client *clnt)
|
|
|
EXPORT_SYMBOL(p9_is_proto_dotu);
|
|
|
|
|
|
/* Interpret mount option for protocol version */
|
|
|
-static int get_protocol_version(const substring_t *name)
|
|
|
+static int get_protocol_version(char *s)
|
|
|
{
|
|
|
int version = -EINVAL;
|
|
|
|
|
|
- if (!strncmp("9p2000", name->from, name->to-name->from)) {
|
|
|
+ if (!strcmp(s, "9p2000")) {
|
|
|
version = p9_proto_legacy;
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
|
|
|
- } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
|
|
|
+ } else if (!strcmp(s, "9p2000.u")) {
|
|
|
version = p9_proto_2000u;
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
|
|
|
- } else if (!strncmp("9p2000.L", name->from, name->to-name->from)) {
|
|
|
+ } else if (!strcmp(s, "9p2000.L")) {
|
|
|
version = p9_proto_2000L;
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
|
|
|
- } else {
|
|
|
- P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
|
|
|
- name->from);
|
|
|
- }
|
|
|
+ } else
|
|
|
+ printk(KERN_INFO "9p: Unknown protocol version %s.\n", s);
|
|
|
+
|
|
|
return version;
|
|
|
}
|
|
|
|
|
@@ -106,6 +105,7 @@ static int parse_opts(char *opts, struct p9_client *clnt)
|
|
|
char *p;
|
|
|
substring_t args[MAX_OPT_ARGS];
|
|
|
int option;
|
|
|
+ char *s;
|
|
|
int ret = 0;
|
|
|
|
|
|
clnt->proto_version = p9_proto_2000u;
|
|
@@ -141,22 +141,41 @@ static int parse_opts(char *opts, struct p9_client *clnt)
|
|
|
clnt->msize = option;
|
|
|
break;
|
|
|
case Opt_trans:
|
|
|
- clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
|
|
|
- if(clnt->trans_mod == NULL) {
|
|
|
+ s = match_strdup(&args[0]);
|
|
|
+ if (!s) {
|
|
|
+ ret = -ENOMEM;
|
|
|
P9_DPRINTK(P9_DEBUG_ERROR,
|
|
|
- "Could not find request transport: %s\n",
|
|
|
- (char *) &args[0]);
|
|
|
+ "problem allocating copy of trans arg\n");
|
|
|
+ goto free_and_return;
|
|
|
+ }
|
|
|
+ clnt->trans_mod = v9fs_get_trans_by_name(s);
|
|
|
+ if (clnt->trans_mod == NULL) {
|
|
|
+ printk(KERN_INFO
|
|
|
+ "9p: Could not find "
|
|
|
+ "request transport: %s\n", s);
|
|
|
ret = -EINVAL;
|
|
|
+ kfree(s);
|
|
|
goto free_and_return;
|
|
|
}
|
|
|
+ kfree(s);
|
|
|
break;
|
|
|
case Opt_legacy:
|
|
|
clnt->proto_version = p9_proto_legacy;
|
|
|
break;
|
|
|
case Opt_version:
|
|
|
- ret = get_protocol_version(&args[0]);
|
|
|
- if (ret == -EINVAL)
|
|
|
+ s = match_strdup(&args[0]);
|
|
|
+ if (!s) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ P9_DPRINTK(P9_DEBUG_ERROR,
|
|
|
+ "problem allocating copy of version arg\n");
|
|
|
goto free_and_return;
|
|
|
+ }
|
|
|
+ ret = get_protocol_version(s);
|
|
|
+ if (ret == -EINVAL) {
|
|
|
+ kfree(s);
|
|
|
+ goto free_and_return;
|
|
|
+ }
|
|
|
+ kfree(s);
|
|
|
clnt->proto_version = ret;
|
|
|
break;
|
|
|
default:
|
|
@@ -280,7 +299,8 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
|
|
|
* buffer to read the data into */
|
|
|
tag++;
|
|
|
|
|
|
- BUG_ON(tag >= c->max_tag);
|
|
|
+ if(tag >= c->max_tag)
|
|
|
+ return NULL;
|
|
|
|
|
|
row = tag / P9_ROW_MAXTAG;
|
|
|
col = tag % P9_ROW_MAXTAG;
|
|
@@ -749,7 +769,7 @@ static int p9_client_version(struct p9_client *c)
|
|
|
err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
|
|
|
if (err) {
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
@@ -821,8 +841,8 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
|
|
|
if (err)
|
|
|
goto destroy_fidpool;
|
|
|
|
|
|
- if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
|
|
|
- clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
|
|
|
+ if (clnt->msize > clnt->trans_mod->maxsize)
|
|
|
+ clnt->msize = clnt->trans_mod->maxsize;
|
|
|
|
|
|
err = p9_client_version(clnt);
|
|
|
if (err)
|
|
@@ -911,7 +931,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
p9_free_req(clnt, req);
|
|
|
goto error;
|
|
|
}
|
|
@@ -971,7 +991,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
p9_free_req(clnt, req);
|
|
|
goto clunk_fid;
|
|
|
}
|
|
@@ -1038,7 +1058,7 @@ int p9_client_open(struct p9_fid *fid, int mode)
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto free_and_error;
|
|
|
}
|
|
|
|
|
@@ -1081,7 +1101,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto free_and_error;
|
|
|
}
|
|
|
|
|
@@ -1126,7 +1146,7 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto free_and_error;
|
|
|
}
|
|
|
|
|
@@ -1165,7 +1185,7 @@ int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto free_and_error;
|
|
|
}
|
|
|
|
|
@@ -1249,9 +1269,11 @@ int p9_client_clunk(struct p9_fid *fid)
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
|
|
|
|
|
|
p9_free_req(clnt, req);
|
|
|
- p9_fid_destroy(fid);
|
|
|
-
|
|
|
error:
|
|
|
+ /*
|
|
|
+ * Fid is not valid even after a failed clunk
|
|
|
+ */
|
|
|
+ p9_fid_destroy(fid);
|
|
|
return err;
|
|
|
}
|
|
|
EXPORT_SYMBOL(p9_client_clunk);
|
|
@@ -1281,6 +1303,29 @@ error:
|
|
|
}
|
|
|
EXPORT_SYMBOL(p9_client_remove);
|
|
|
|
|
|
+int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags)
|
|
|
+{
|
|
|
+ int err = 0;
|
|
|
+ struct p9_req_t *req;
|
|
|
+ struct p9_client *clnt;
|
|
|
+
|
|
|
+ P9_DPRINTK(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n",
|
|
|
+ dfid->fid, name, flags);
|
|
|
+
|
|
|
+ clnt = dfid->clnt;
|
|
|
+ req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags);
|
|
|
+ if (IS_ERR(req)) {
|
|
|
+ err = PTR_ERR(req);
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ P9_DPRINTK(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name);
|
|
|
+
|
|
|
+ p9_free_req(clnt, req);
|
|
|
+error:
|
|
|
+ return err;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(p9_client_unlinkat);
|
|
|
+
|
|
|
int
|
|
|
p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
|
|
|
u32 count)
|
|
@@ -1318,11 +1363,12 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto free_and_error;
|
|
|
}
|
|
|
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
|
|
|
if (!req->tc->pbuf_size) {
|
|
|
if (data) {
|
|
@@ -1386,7 +1432,7 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto free_and_error;
|
|
|
}
|
|
|
|
|
@@ -1426,7 +1472,7 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
p9_free_req(clnt, req);
|
|
|
goto error;
|
|
|
}
|
|
@@ -1477,7 +1523,7 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
p9_free_req(clnt, req);
|
|
|
goto error;
|
|
|
}
|
|
@@ -1625,7 +1671,7 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
|
|
|
&sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
|
|
|
&sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
p9_free_req(clnt, req);
|
|
|
goto error;
|
|
|
}
|
|
@@ -1643,7 +1689,8 @@ error:
|
|
|
}
|
|
|
EXPORT_SYMBOL(p9_client_statfs);
|
|
|
|
|
|
-int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name)
|
|
|
+int p9_client_rename(struct p9_fid *fid,
|
|
|
+ struct p9_fid *newdirfid, const char *name)
|
|
|
{
|
|
|
int err;
|
|
|
struct p9_req_t *req;
|
|
@@ -1670,6 +1717,36 @@ error:
|
|
|
}
|
|
|
EXPORT_SYMBOL(p9_client_rename);
|
|
|
|
|
|
+int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
|
|
|
+ struct p9_fid *newdirfid, const char *new_name)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+ struct p9_req_t *req;
|
|
|
+ struct p9_client *clnt;
|
|
|
+
|
|
|
+ err = 0;
|
|
|
+ clnt = olddirfid->clnt;
|
|
|
+
|
|
|
+ P9_DPRINTK(P9_DEBUG_9P, ">>> TRENAMEAT olddirfid %d old name %s"
|
|
|
+ " newdirfid %d new name %s\n", olddirfid->fid, old_name,
|
|
|
+ newdirfid->fid, new_name);
|
|
|
+
|
|
|
+ req = p9_client_rpc(clnt, P9_TRENAMEAT, "dsds", olddirfid->fid,
|
|
|
+ old_name, newdirfid->fid, new_name);
|
|
|
+ if (IS_ERR(req)) {
|
|
|
+ err = PTR_ERR(req);
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ P9_DPRINTK(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n",
|
|
|
+ newdirfid->fid, new_name);
|
|
|
+
|
|
|
+ p9_free_req(clnt, req);
|
|
|
+error:
|
|
|
+ return err;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(p9_client_renameat);
|
|
|
+
|
|
|
/*
|
|
|
* An xattrwalk without @attr_name gives the fid for the lisxattr namespace
|
|
|
*/
|
|
@@ -1701,7 +1778,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
|
|
|
}
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
p9_free_req(clnt, req);
|
|
|
goto clunk_fid;
|
|
|
}
|
|
@@ -1780,7 +1857,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto free_and_error;
|
|
|
}
|
|
|
|
|
@@ -1817,7 +1894,7 @@ int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto error;
|
|
|
}
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
|
|
@@ -1848,7 +1925,7 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto error;
|
|
|
}
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type,
|
|
@@ -1883,7 +1960,7 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "b", status);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto error;
|
|
|
}
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status);
|
|
@@ -1916,7 +1993,7 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
|
|
|
&glock->start, &glock->length, &glock->proc_id,
|
|
|
&glock->client_id);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto error;
|
|
|
}
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld "
|
|
@@ -1944,7 +2021,7 @@ int p9_client_readlink(struct p9_fid *fid, char **target)
|
|
|
|
|
|
err = p9pdu_readf(req->rc, clnt->proto_version, "s", target);
|
|
|
if (err) {
|
|
|
- p9pdu_dump(1, req->rc);
|
|
|
+ P9_DUMP_PKT(1, req->rc);
|
|
|
goto error;
|
|
|
}
|
|
|
P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
|