diff options
Diffstat (limited to 'net/9p/client.c')
| -rw-r--r-- | net/9p/client.c | 155 | 
1 files changed, 116 insertions, 39 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 9e3b0e640da1..0505a03c374c 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -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);  |