aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorM. Mohan Kumar <mohan@in.ibm.com>2010-06-16 04:57:01 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2010-08-02 15:28:30 -0400
commit4b43516ab19b748b48322937fd9307af17541c4d (patch)
tree0ab84e8d69abce9d63e1937b1a807d2243444a01
parent50cc42ff3d7bc48a436c5a0413459ca7841b505f (diff)
9p: Implement TMKNOD
Synopsis size[4] Tmknod tag[2] fid[4] name[s] mode[4] major[4] minor[4] gid[4] size[4] Rmknod tag[2] qid[13] Description mknod asks the file server to create a device node with given major and minor number, mode and gid. The qid for the new device node is returned with the mknod reply message. [sripathik@in.ibm.com: Fix error handling code] Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com> Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--fs/9p/vfs_inode.c106
-rw-r--r--include/net/9p/9p.h4
-rw-r--r--include/net/9p/client.h2
-rw-r--r--net/9p/client.c31
4 files changed, 140 insertions, 3 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index a7319364544b..4d9f45ec6126 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -302,7 +302,13 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
302 case S_IFBLK: 302 case S_IFBLK:
303 case S_IFCHR: 303 case S_IFCHR:
304 case S_IFSOCK: 304 case S_IFSOCK:
305 if (!v9fs_proto_dotu(v9ses)) { 305 if (v9fs_proto_dotl(v9ses)) {
306 inode->i_op = &v9fs_file_inode_operations_dotl;
307 inode->i_fop = &v9fs_file_operations_dotl;
308 } else if (v9fs_proto_dotu(v9ses)) {
309 inode->i_op = &v9fs_file_inode_operations;
310 inode->i_fop = &v9fs_file_operations;
311 } else {
306 P9_DPRINTK(P9_DEBUG_ERROR, 312 P9_DPRINTK(P9_DEBUG_ERROR,
307 "special files without extended mode\n"); 313 "special files without extended mode\n");
308 err = -EINVAL; 314 err = -EINVAL;
@@ -1616,6 +1622,100 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1616 return retval; 1622 return retval;
1617} 1623}
1618 1624
1625/**
1626 * v9fs_vfs_mknod_dotl - create a special file
1627 * @dir: inode destination for new link
1628 * @dentry: dentry for file
1629 * @mode: mode for creation
1630 * @rdev: device associated with special file
1631 *
1632 */
1633static int
1634v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode,
1635 dev_t rdev)
1636{
1637 int err;
1638 char *name;
1639 struct v9fs_session_info *v9ses;
1640 struct p9_fid *fid = NULL, *dfid = NULL;
1641 struct inode *inode;
1642 gid_t gid;
1643 struct p9_qid qid;
1644 struct dentry *dir_entry;
1645
1646 P9_DPRINTK(P9_DEBUG_VFS,
1647 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
1648 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
1649
1650 if (!new_valid_dev(rdev))
1651 return -EINVAL;
1652
1653 v9ses = v9fs_inode2v9ses(dir);
1654 dir_dentry = v9fs_dentry_from_dir_inode(dir);
1655 dfid = v9fs_fid_lookup(dir_entry);
1656 if (IS_ERR(dfid)) {
1657 err = PTR_ERR(dfid);
1658 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
1659 dfid = NULL;
1660 goto error;
1661 }
1662
1663 gid = v9fs_get_fsgid_for_create(dir);
1664 if (gid < 0) {
1665 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n");
1666 goto error;
1667 }
1668
1669 name = (char *) dentry->d_name.name;
1670
1671 err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid);
1672 if (err < 0)
1673 goto error;
1674
1675 /* instantiate inode and assign the unopened fid to the dentry */
1676 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1677 fid = p9_client_walk(dfid, 1, &name, 1);
1678 if (IS_ERR(fid)) {
1679 err = PTR_ERR(fid);
1680 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
1681 err);
1682 fid = NULL;
1683 goto error;
1684 }
1685
1686 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
1687 if (IS_ERR(inode)) {
1688 err = PTR_ERR(inode);
1689 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
1690 err);
1691 goto error;
1692 }
1693 dentry->d_op = &v9fs_cached_dentry_operations;
1694 d_instantiate(dentry, inode);
1695 err = v9fs_fid_add(dentry, fid);
1696 if (err < 0)
1697 goto error;
1698 fid = NULL;
1699 } else {
1700 /*
1701 * Not in cached mode. No need to populate inode with stat.
1702 * socket syscall returns a fd, so we need instantiate
1703 */
1704 inode = v9fs_get_inode(dir->i_sb, mode);
1705 if (IS_ERR(inode)) {
1706 err = PTR_ERR(inode);
1707 goto error;
1708 }
1709 dentry->d_op = &v9fs_dentry_operations;
1710 d_instantiate(dentry, inode);
1711 }
1712
1713error:
1714 if (fid)
1715 p9_client_clunk(fid);
1716 return err;
1717}
1718
1619static const struct inode_operations v9fs_dir_inode_operations_dotu = { 1719static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1620 .create = v9fs_vfs_create, 1720 .create = v9fs_vfs_create,
1621 .lookup = v9fs_vfs_lookup, 1721 .lookup = v9fs_vfs_lookup,
@@ -1624,7 +1724,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1624 .unlink = v9fs_vfs_unlink, 1724 .unlink = v9fs_vfs_unlink,
1625 .mkdir = v9fs_vfs_mkdir, 1725 .mkdir = v9fs_vfs_mkdir,
1626 .rmdir = v9fs_vfs_rmdir, 1726 .rmdir = v9fs_vfs_rmdir,
1627 .mknod = v9fs_vfs_mknod, 1727 .mknod = v9fs_vfs_mknod_dotl,
1628 .rename = v9fs_vfs_rename, 1728 .rename = v9fs_vfs_rename,
1629 .getattr = v9fs_vfs_getattr, 1729 .getattr = v9fs_vfs_getattr,
1630 .setattr = v9fs_vfs_setattr, 1730 .setattr = v9fs_vfs_setattr,
@@ -1638,7 +1738,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotl = {
1638 .unlink = v9fs_vfs_unlink, 1738 .unlink = v9fs_vfs_unlink,
1639 .mkdir = v9fs_vfs_mkdir, 1739 .mkdir = v9fs_vfs_mkdir,
1640 .rmdir = v9fs_vfs_rmdir, 1740 .rmdir = v9fs_vfs_rmdir,
1641 .mknod = v9fs_vfs_mknod, 1741 .mknod = v9fs_vfs_mknod_dotl,
1642 .rename = v9fs_vfs_rename, 1742 .rename = v9fs_vfs_rename,
1643 .getattr = v9fs_vfs_getattr_dotl, 1743 .getattr = v9fs_vfs_getattr_dotl,
1644 .setattr = v9fs_vfs_setattr_dotl, 1744 .setattr = v9fs_vfs_setattr_dotl,
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 44a6883d7144..ff32091d8063 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -90,6 +90,8 @@ do { \
90 * @P9_RSTATFS: file system status response 90 * @P9_RSTATFS: file system status response
91 * @P9_TSYMLINK: make symlink request 91 * @P9_TSYMLINK: make symlink request
92 * @P9_RSYMLINK: make symlink response 92 * @P9_RSYMLINK: make symlink response
93 * @P9_TMKNOD: create a special file object request
94 * @P9_RMKNOD: create a special file object response
93 * @P9_TRENAME: rename request 95 * @P9_TRENAME: rename request
94 * @P9_RRENAME: rename response 96 * @P9_RRENAME: rename response
95 * @P9_TVERSION: version handshake request 97 * @P9_TVERSION: version handshake request
@@ -135,6 +137,8 @@ enum p9_msg_t {
135 P9_RSTATFS, 137 P9_RSTATFS,
136 P9_TSYMLINK = 16, 138 P9_TSYMLINK = 16,
137 P9_RSYMLINK, 139 P9_RSYMLINK,
140 P9_TMKNOD = 18,
141 P9_RMKNOD,
138 P9_TRENAME = 20, 142 P9_TRENAME = 20,
139 P9_RRENAME, 143 P9_RRENAME,
140 P9_TGETATTR = 24, 144 P9_TGETATTR = 24,
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 2e039730920e..6e70358c71d9 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -245,6 +245,8 @@ int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr);
245struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, 245struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
246 u64 request_mask); 246 u64 request_mask);
247 247
248int p9_client_mknod_dotl(struct p9_fid *oldfid, char *name, int mode,
249 dev_t rdev, gid_t gid, struct p9_qid *);
248struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); 250struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
249void p9_client_cb(struct p9_client *c, struct p9_req_t *req); 251void p9_client_cb(struct p9_client *c, struct p9_req_t *req);
250 252
diff --git a/net/9p/client.c b/net/9p/client.c
index e37e64cb9394..cdfbd6740796 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1622,3 +1622,34 @@ error:
1622 return err; 1622 return err;
1623} 1623}
1624EXPORT_SYMBOL(p9_client_readdir); 1624EXPORT_SYMBOL(p9_client_readdir);
1625
1626int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
1627 dev_t rdev, gid_t gid, struct p9_qid *qid)
1628{
1629 int err;
1630 struct p9_client *clnt;
1631 struct p9_req_t *req;
1632
1633 err = 0;
1634 clnt = fid->clnt;
1635 P9_DPRINTK(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d "
1636 "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev));
1637 req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddd", fid->fid, name, mode,
1638 MAJOR(rdev), MINOR(rdev), gid);
1639 if (IS_ERR(req))
1640 return PTR_ERR(req);
1641
1642 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
1643 if (err) {
1644 p9pdu_dump(1, req->rc);
1645 goto error;
1646 }
1647 P9_DPRINTK(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
1648 (unsigned long long)qid->path, qid->version);
1649
1650error:
1651 p9_free_req(clnt, req);
1652 return err;
1653
1654}
1655EXPORT_SYMBOL(p9_client_mknod_dotl);