11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * net/sunrpc/rpc_pipe.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Userland/kernel interface for rpcauth_gss. 51da177e4SLinus Torvalds * Code shamelessly plagiarized from fs/nfsd/nfsctl.c 6d51fe1beSRolf Eike Beer * and fs/sysfs/inode.c 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Copyright (c) 2002, Trond Myklebust <trond.myklebust@fys.uio.no> 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds #include <linux/module.h> 121da177e4SLinus Torvalds #include <linux/slab.h> 131da177e4SLinus Torvalds #include <linux/string.h> 141da177e4SLinus Torvalds #include <linux/pagemap.h> 151da177e4SLinus Torvalds #include <linux/mount.h> 161da177e4SLinus Torvalds #include <linux/namei.h> 1750e437d5STrond Myklebust #include <linux/fsnotify.h> 181da177e4SLinus Torvalds #include <linux/kernel.h> 192446ab60STrond Myklebust #include <linux/rcupdate.h> 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds #include <asm/ioctls.h> 221da177e4SLinus Torvalds #include <linux/poll.h> 231da177e4SLinus Torvalds #include <linux/wait.h> 241da177e4SLinus Torvalds #include <linux/seq_file.h> 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h> 271da177e4SLinus Torvalds #include <linux/workqueue.h> 281da177e4SLinus Torvalds #include <linux/sunrpc/rpc_pipe_fs.h> 298854e82dSTrond Myklebust #include <linux/sunrpc/cache.h> 30021c68deSStanislav Kinsbursky #include <linux/nsproxy.h> 312d00131aSStanislav Kinsbursky #include <linux/notifier.h> 321da177e4SLinus Torvalds 33021c68deSStanislav Kinsbursky #include "netns.h" 342d00131aSStanislav Kinsbursky #include "sunrpc.h" 351da177e4SLinus Torvalds 36efc46bf2SStanislav Kinsbursky #define RPCDBG_FACILITY RPCDBG_DEBUG 37efc46bf2SStanislav Kinsbursky 38efc46bf2SStanislav Kinsbursky #define NET_NAME(net) ((net == &init_net) ? " (init_net)" : "") 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds static struct file_system_type rpc_pipe_fs_type; 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds 43e18b890bSChristoph Lameter static struct kmem_cache *rpc_inode_cachep __read_mostly; 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds #define RPC_UPCALL_TIMEOUT (30*HZ) 461da177e4SLinus Torvalds 472d00131aSStanislav Kinsbursky static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list); 482d00131aSStanislav Kinsbursky 492d00131aSStanislav Kinsbursky int rpc_pipefs_notifier_register(struct notifier_block *nb) 502d00131aSStanislav Kinsbursky { 512d00131aSStanislav Kinsbursky return blocking_notifier_chain_cond_register(&rpc_pipefs_notifier_list, nb); 522d00131aSStanislav Kinsbursky } 532d00131aSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_register); 542d00131aSStanislav Kinsbursky 552d00131aSStanislav Kinsbursky void rpc_pipefs_notifier_unregister(struct notifier_block *nb) 562d00131aSStanislav Kinsbursky { 572d00131aSStanislav Kinsbursky blocking_notifier_chain_unregister(&rpc_pipefs_notifier_list, nb); 582d00131aSStanislav Kinsbursky } 592d00131aSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister); 602d00131aSStanislav Kinsbursky 61591ad7feSStanislav Kinsbursky static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head, 629842ef35STrond Myklebust void (*destroy_msg)(struct rpc_pipe_msg *), int err) 63b3eb67a2STrond Myklebust { 64b3eb67a2STrond Myklebust struct rpc_pipe_msg *msg; 65b3eb67a2STrond Myklebust 669842ef35STrond Myklebust if (list_empty(head)) 679842ef35STrond Myklebust return; 689842ef35STrond Myklebust do { 69b3eb67a2STrond Myklebust msg = list_entry(head->next, struct rpc_pipe_msg, list); 705a67657aSTrond Myklebust list_del_init(&msg->list); 71b3eb67a2STrond Myklebust msg->errno = err; 72b3eb67a2STrond Myklebust destroy_msg(msg); 739842ef35STrond Myklebust } while (!list_empty(head)); 7492123e06SJeff Layton 7592123e06SJeff Layton if (waitq) 76591ad7feSStanislav Kinsbursky wake_up(waitq); 771da177e4SLinus Torvalds } 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds static void 8065f27f38SDavid Howells rpc_timeout_upcall_queue(struct work_struct *work) 811da177e4SLinus Torvalds { 829842ef35STrond Myklebust LIST_HEAD(free_list); 83ba9e0975SStanislav Kinsbursky struct rpc_pipe *pipe = 84ba9e0975SStanislav Kinsbursky container_of(work, struct rpc_pipe, queue_timeout.work); 859842ef35STrond Myklebust void (*destroy_msg)(struct rpc_pipe_msg *); 86591ad7feSStanislav Kinsbursky struct dentry *dentry; 871da177e4SLinus Torvalds 88ba9e0975SStanislav Kinsbursky spin_lock(&pipe->lock); 89ba9e0975SStanislav Kinsbursky destroy_msg = pipe->ops->destroy_msg; 90ba9e0975SStanislav Kinsbursky if (pipe->nreaders == 0) { 91ba9e0975SStanislav Kinsbursky list_splice_init(&pipe->pipe, &free_list); 92ba9e0975SStanislav Kinsbursky pipe->pipelen = 0; 939842ef35STrond Myklebust } 94591ad7feSStanislav Kinsbursky dentry = dget(pipe->dentry); 95ba9e0975SStanislav Kinsbursky spin_unlock(&pipe->lock); 9692123e06SJeff Layton rpc_purge_list(dentry ? &RPC_I(dentry->d_inode)->waitq : NULL, 97591ad7feSStanislav Kinsbursky &free_list, destroy_msg, -ETIMEDOUT); 98591ad7feSStanislav Kinsbursky dput(dentry); 999842ef35STrond Myklebust } 1001da177e4SLinus Torvalds 101c1225158SPeng Tao ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, 102c1225158SPeng Tao char __user *dst, size_t buflen) 103c1225158SPeng Tao { 104c1225158SPeng Tao char *data = (char *)msg->data + msg->copied; 105c1225158SPeng Tao size_t mlen = min(msg->len - msg->copied, buflen); 106c1225158SPeng Tao unsigned long left; 107c1225158SPeng Tao 108c1225158SPeng Tao left = copy_to_user(dst, data, mlen); 109c1225158SPeng Tao if (left == mlen) { 110c1225158SPeng Tao msg->errno = -EFAULT; 111c1225158SPeng Tao return -EFAULT; 112c1225158SPeng Tao } 113c1225158SPeng Tao 114c1225158SPeng Tao mlen -= left; 115c1225158SPeng Tao msg->copied += mlen; 116c1225158SPeng Tao msg->errno = 0; 117c1225158SPeng Tao return mlen; 118c1225158SPeng Tao } 119c1225158SPeng Tao EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall); 120c1225158SPeng Tao 12193a44a75SJ. Bruce Fields /** 1221a5778aaSBen Hutchings * rpc_queue_upcall - queue an upcall message to userspace 123bda14606SRandy Dunlap * @pipe: upcall pipe on which to queue given message 12493a44a75SJ. Bruce Fields * @msg: message to queue 12593a44a75SJ. Bruce Fields * 12693a44a75SJ. Bruce Fields * Call with an @inode created by rpc_mkpipe() to queue an upcall. 12793a44a75SJ. Bruce Fields * A userspace process may then later read the upcall by performing a 12893a44a75SJ. Bruce Fields * read on an open file for this inode. It is up to the caller to 12993a44a75SJ. Bruce Fields * initialize the fields of @msg (other than @msg->list) appropriately. 13093a44a75SJ. Bruce Fields */ 1311da177e4SLinus Torvalds int 132d706ed1fSStanislav Kinsbursky rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) 1331da177e4SLinus Torvalds { 1346070fe6fSTrond Myklebust int res = -EPIPE; 135591ad7feSStanislav Kinsbursky struct dentry *dentry; 1361da177e4SLinus Torvalds 137d0fe13baSStanislav Kinsbursky spin_lock(&pipe->lock); 138d0fe13baSStanislav Kinsbursky if (pipe->nreaders) { 139d0fe13baSStanislav Kinsbursky list_add_tail(&msg->list, &pipe->pipe); 140d0fe13baSStanislav Kinsbursky pipe->pipelen += msg->len; 1416070fe6fSTrond Myklebust res = 0; 142d0fe13baSStanislav Kinsbursky } else if (pipe->flags & RPC_PIPE_WAIT_FOR_OPEN) { 143d0fe13baSStanislav Kinsbursky if (list_empty(&pipe->pipe)) 14424c5d9d7STrond Myklebust queue_delayed_work(rpciod_workqueue, 145d0fe13baSStanislav Kinsbursky &pipe->queue_timeout, 1461da177e4SLinus Torvalds RPC_UPCALL_TIMEOUT); 147d0fe13baSStanislav Kinsbursky list_add_tail(&msg->list, &pipe->pipe); 148d0fe13baSStanislav Kinsbursky pipe->pipelen += msg->len; 1496070fe6fSTrond Myklebust res = 0; 1506070fe6fSTrond Myklebust } 151591ad7feSStanislav Kinsbursky dentry = dget(pipe->dentry); 152d0fe13baSStanislav Kinsbursky spin_unlock(&pipe->lock); 153591ad7feSStanislav Kinsbursky if (dentry) { 154591ad7feSStanislav Kinsbursky wake_up(&RPC_I(dentry->d_inode)->waitq); 155591ad7feSStanislav Kinsbursky dput(dentry); 156591ad7feSStanislav Kinsbursky } 1571da177e4SLinus Torvalds return res; 1581da177e4SLinus Torvalds } 159468039eeSTrond Myklebust EXPORT_SYMBOL_GPL(rpc_queue_upcall); 1601da177e4SLinus Torvalds 1616070fe6fSTrond Myklebust static inline void 1626070fe6fSTrond Myklebust rpc_inode_setowner(struct inode *inode, void *private) 1636070fe6fSTrond Myklebust { 1646070fe6fSTrond Myklebust RPC_I(inode)->private = private; 1656070fe6fSTrond Myklebust } 1666070fe6fSTrond Myklebust 1671da177e4SLinus Torvalds static void 1681da177e4SLinus Torvalds rpc_close_pipes(struct inode *inode) 1691da177e4SLinus Torvalds { 170ba9e0975SStanislav Kinsbursky struct rpc_pipe *pipe = RPC_I(inode)->pipe; 171e712804aS\"J. Bruce Fields\ int need_release; 172ad6b1340SStanislav Kinsbursky LIST_HEAD(free_list); 1731da177e4SLinus Torvalds 1741b1dcc1bSJes Sorensen mutex_lock(&inode->i_mutex); 175ba9e0975SStanislav Kinsbursky spin_lock(&pipe->lock); 176ba9e0975SStanislav Kinsbursky need_release = pipe->nreaders != 0 || pipe->nwriters != 0; 177ba9e0975SStanislav Kinsbursky pipe->nreaders = 0; 178ba9e0975SStanislav Kinsbursky list_splice_init(&pipe->in_upcall, &free_list); 179ba9e0975SStanislav Kinsbursky list_splice_init(&pipe->pipe, &free_list); 180ba9e0975SStanislav Kinsbursky pipe->pipelen = 0; 181ad6b1340SStanislav Kinsbursky pipe->dentry = NULL; 182ba9e0975SStanislav Kinsbursky spin_unlock(&pipe->lock); 183591ad7feSStanislav Kinsbursky rpc_purge_list(&RPC_I(inode)->waitq, &free_list, pipe->ops->destroy_msg, -EPIPE); 184ba9e0975SStanislav Kinsbursky pipe->nwriters = 0; 185ad6b1340SStanislav Kinsbursky if (need_release && pipe->ops->release_pipe) 186ad6b1340SStanislav Kinsbursky pipe->ops->release_pipe(inode); 187ba9e0975SStanislav Kinsbursky cancel_delayed_work_sync(&pipe->queue_timeout); 1886070fe6fSTrond Myklebust rpc_inode_setowner(inode, NULL); 1892c9030eeSStanislav Kinsbursky RPC_I(inode)->pipe = NULL; 1901b1dcc1bSJes Sorensen mutex_unlock(&inode->i_mutex); 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds static struct inode * 1941da177e4SLinus Torvalds rpc_alloc_inode(struct super_block *sb) 1951da177e4SLinus Torvalds { 1961da177e4SLinus Torvalds struct rpc_inode *rpci; 197e94b1766SChristoph Lameter rpci = (struct rpc_inode *)kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL); 1981da177e4SLinus Torvalds if (!rpci) 1991da177e4SLinus Torvalds return NULL; 2001da177e4SLinus Torvalds return &rpci->vfs_inode; 2011da177e4SLinus Torvalds } 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds static void 204fa0d7e3dSNick Piggin rpc_i_callback(struct rcu_head *head) 205fa0d7e3dSNick Piggin { 206fa0d7e3dSNick Piggin struct inode *inode = container_of(head, struct inode, i_rcu); 207fa0d7e3dSNick Piggin kmem_cache_free(rpc_inode_cachep, RPC_I(inode)); 208fa0d7e3dSNick Piggin } 209fa0d7e3dSNick Piggin 210fa0d7e3dSNick Piggin static void 2111da177e4SLinus Torvalds rpc_destroy_inode(struct inode *inode) 2121da177e4SLinus Torvalds { 213fa0d7e3dSNick Piggin call_rcu(&inode->i_rcu, rpc_i_callback); 2141da177e4SLinus Torvalds } 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds static int 2171da177e4SLinus Torvalds rpc_pipe_open(struct inode *inode, struct file *filp) 2181da177e4SLinus Torvalds { 219abfdbd53STrond Myklebust struct net *net = inode->i_sb->s_fs_info; 220abfdbd53STrond Myklebust struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 2212c9030eeSStanislav Kinsbursky struct rpc_pipe *pipe; 222c3810608S\"J. Bruce Fields\ int first_open; 2231da177e4SLinus Torvalds int res = -ENXIO; 2241da177e4SLinus Torvalds 2251b1dcc1bSJes Sorensen mutex_lock(&inode->i_mutex); 226abfdbd53STrond Myklebust sn->gssd_running = 1; 2272c9030eeSStanislav Kinsbursky pipe = RPC_I(inode)->pipe; 2282c9030eeSStanislav Kinsbursky if (pipe == NULL) 229c3810608S\"J. Bruce Fields\ goto out; 230d0fe13baSStanislav Kinsbursky first_open = pipe->nreaders == 0 && pipe->nwriters == 0; 231d0fe13baSStanislav Kinsbursky if (first_open && pipe->ops->open_pipe) { 232d0fe13baSStanislav Kinsbursky res = pipe->ops->open_pipe(inode); 233c3810608S\"J. Bruce Fields\ if (res) 234c3810608S\"J. Bruce Fields\ goto out; 235c3810608S\"J. Bruce Fields\ } 2361da177e4SLinus Torvalds if (filp->f_mode & FMODE_READ) 237d0fe13baSStanislav Kinsbursky pipe->nreaders++; 2381da177e4SLinus Torvalds if (filp->f_mode & FMODE_WRITE) 239d0fe13baSStanislav Kinsbursky pipe->nwriters++; 2401da177e4SLinus Torvalds res = 0; 241c3810608S\"J. Bruce Fields\ out: 2421b1dcc1bSJes Sorensen mutex_unlock(&inode->i_mutex); 2431da177e4SLinus Torvalds return res; 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds static int 2471da177e4SLinus Torvalds rpc_pipe_release(struct inode *inode, struct file *filp) 2481da177e4SLinus Torvalds { 2492c9030eeSStanislav Kinsbursky struct rpc_pipe *pipe; 2501da177e4SLinus Torvalds struct rpc_pipe_msg *msg; 251e712804aS\"J. Bruce Fields\ int last_close; 2521da177e4SLinus Torvalds 2531b1dcc1bSJes Sorensen mutex_lock(&inode->i_mutex); 2542c9030eeSStanislav Kinsbursky pipe = RPC_I(inode)->pipe; 2552c9030eeSStanislav Kinsbursky if (pipe == NULL) 2561da177e4SLinus Torvalds goto out; 257655b5bb4SJoe Perches msg = filp->private_data; 2581da177e4SLinus Torvalds if (msg != NULL) { 259ba9e0975SStanislav Kinsbursky spin_lock(&pipe->lock); 26048e49187STrond Myklebust msg->errno = -EAGAIN; 2615a67657aSTrond Myklebust list_del_init(&msg->list); 262ba9e0975SStanislav Kinsbursky spin_unlock(&pipe->lock); 263ba9e0975SStanislav Kinsbursky pipe->ops->destroy_msg(msg); 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds if (filp->f_mode & FMODE_WRITE) 266ba9e0975SStanislav Kinsbursky pipe->nwriters --; 2679842ef35STrond Myklebust if (filp->f_mode & FMODE_READ) { 268ba9e0975SStanislav Kinsbursky pipe->nreaders --; 269ba9e0975SStanislav Kinsbursky if (pipe->nreaders == 0) { 2709842ef35STrond Myklebust LIST_HEAD(free_list); 271ba9e0975SStanislav Kinsbursky spin_lock(&pipe->lock); 272ba9e0975SStanislav Kinsbursky list_splice_init(&pipe->pipe, &free_list); 273ba9e0975SStanislav Kinsbursky pipe->pipelen = 0; 274ba9e0975SStanislav Kinsbursky spin_unlock(&pipe->lock); 275591ad7feSStanislav Kinsbursky rpc_purge_list(&RPC_I(inode)->waitq, &free_list, 276ba9e0975SStanislav Kinsbursky pipe->ops->destroy_msg, -EAGAIN); 2779842ef35STrond Myklebust } 2789842ef35STrond Myklebust } 279ba9e0975SStanislav Kinsbursky last_close = pipe->nwriters == 0 && pipe->nreaders == 0; 280ba9e0975SStanislav Kinsbursky if (last_close && pipe->ops->release_pipe) 281ba9e0975SStanislav Kinsbursky pipe->ops->release_pipe(inode); 2821da177e4SLinus Torvalds out: 2831b1dcc1bSJes Sorensen mutex_unlock(&inode->i_mutex); 2841da177e4SLinus Torvalds return 0; 2851da177e4SLinus Torvalds } 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds static ssize_t 2881da177e4SLinus Torvalds rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) 2891da177e4SLinus Torvalds { 290496ad9aaSAl Viro struct inode *inode = file_inode(filp); 2912c9030eeSStanislav Kinsbursky struct rpc_pipe *pipe; 2921da177e4SLinus Torvalds struct rpc_pipe_msg *msg; 2931da177e4SLinus Torvalds int res = 0; 2941da177e4SLinus Torvalds 2951b1dcc1bSJes Sorensen mutex_lock(&inode->i_mutex); 2962c9030eeSStanislav Kinsbursky pipe = RPC_I(inode)->pipe; 2972c9030eeSStanislav Kinsbursky if (pipe == NULL) { 2981da177e4SLinus Torvalds res = -EPIPE; 2991da177e4SLinus Torvalds goto out_unlock; 3001da177e4SLinus Torvalds } 3011da177e4SLinus Torvalds msg = filp->private_data; 3021da177e4SLinus Torvalds if (msg == NULL) { 303d0fe13baSStanislav Kinsbursky spin_lock(&pipe->lock); 304d0fe13baSStanislav Kinsbursky if (!list_empty(&pipe->pipe)) { 305d0fe13baSStanislav Kinsbursky msg = list_entry(pipe->pipe.next, 3061da177e4SLinus Torvalds struct rpc_pipe_msg, 3071da177e4SLinus Torvalds list); 308d0fe13baSStanislav Kinsbursky list_move(&msg->list, &pipe->in_upcall); 309d0fe13baSStanislav Kinsbursky pipe->pipelen -= msg->len; 3101da177e4SLinus Torvalds filp->private_data = msg; 3111da177e4SLinus Torvalds msg->copied = 0; 3121da177e4SLinus Torvalds } 313d0fe13baSStanislav Kinsbursky spin_unlock(&pipe->lock); 3141da177e4SLinus Torvalds if (msg == NULL) 3151da177e4SLinus Torvalds goto out_unlock; 3161da177e4SLinus Torvalds } 3171da177e4SLinus Torvalds /* NOTE: it is up to the callback to update msg->copied */ 318d0fe13baSStanislav Kinsbursky res = pipe->ops->upcall(filp, msg, buf, len); 3191da177e4SLinus Torvalds if (res < 0 || msg->len == msg->copied) { 3201da177e4SLinus Torvalds filp->private_data = NULL; 321d0fe13baSStanislav Kinsbursky spin_lock(&pipe->lock); 3225a67657aSTrond Myklebust list_del_init(&msg->list); 323d0fe13baSStanislav Kinsbursky spin_unlock(&pipe->lock); 324d0fe13baSStanislav Kinsbursky pipe->ops->destroy_msg(msg); 3251da177e4SLinus Torvalds } 3261da177e4SLinus Torvalds out_unlock: 3271b1dcc1bSJes Sorensen mutex_unlock(&inode->i_mutex); 3281da177e4SLinus Torvalds return res; 3291da177e4SLinus Torvalds } 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds static ssize_t 3321da177e4SLinus Torvalds rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) 3331da177e4SLinus Torvalds { 334496ad9aaSAl Viro struct inode *inode = file_inode(filp); 3351da177e4SLinus Torvalds int res; 3361da177e4SLinus Torvalds 3371b1dcc1bSJes Sorensen mutex_lock(&inode->i_mutex); 3381da177e4SLinus Torvalds res = -EPIPE; 3392c9030eeSStanislav Kinsbursky if (RPC_I(inode)->pipe != NULL) 3402c9030eeSStanislav Kinsbursky res = RPC_I(inode)->pipe->ops->downcall(filp, buf, len); 3411b1dcc1bSJes Sorensen mutex_unlock(&inode->i_mutex); 3421da177e4SLinus Torvalds return res; 3431da177e4SLinus Torvalds } 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds static unsigned int 3461da177e4SLinus Torvalds rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) 3471da177e4SLinus Torvalds { 348496ad9aaSAl Viro struct inode *inode = file_inode(filp); 349591ad7feSStanislav Kinsbursky struct rpc_inode *rpci = RPC_I(inode); 350591ad7feSStanislav Kinsbursky unsigned int mask = POLLOUT | POLLWRNORM; 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds poll_wait(filp, &rpci->waitq, wait); 3531da177e4SLinus Torvalds 354591ad7feSStanislav Kinsbursky mutex_lock(&inode->i_mutex); 355591ad7feSStanislav Kinsbursky if (rpci->pipe == NULL) 3561da177e4SLinus Torvalds mask |= POLLERR | POLLHUP; 357591ad7feSStanislav Kinsbursky else if (filp->private_data || !list_empty(&rpci->pipe->pipe)) 3581da177e4SLinus Torvalds mask |= POLLIN | POLLRDNORM; 359591ad7feSStanislav Kinsbursky mutex_unlock(&inode->i_mutex); 3601da177e4SLinus Torvalds return mask; 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds 363a6f8dbc6SArnd Bergmann static long 364a6f8dbc6SArnd Bergmann rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 3651da177e4SLinus Torvalds { 366496ad9aaSAl Viro struct inode *inode = file_inode(filp); 3672c9030eeSStanislav Kinsbursky struct rpc_pipe *pipe; 3681da177e4SLinus Torvalds int len; 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds switch (cmd) { 3711da177e4SLinus Torvalds case FIONREAD: 3722c9030eeSStanislav Kinsbursky mutex_lock(&inode->i_mutex); 3732c9030eeSStanislav Kinsbursky pipe = RPC_I(inode)->pipe; 3742c9030eeSStanislav Kinsbursky if (pipe == NULL) { 3752c9030eeSStanislav Kinsbursky mutex_unlock(&inode->i_mutex); 3761da177e4SLinus Torvalds return -EPIPE; 377a6f8dbc6SArnd Bergmann } 3782c9030eeSStanislav Kinsbursky spin_lock(&pipe->lock); 379d0fe13baSStanislav Kinsbursky len = pipe->pipelen; 3801da177e4SLinus Torvalds if (filp->private_data) { 3811da177e4SLinus Torvalds struct rpc_pipe_msg *msg; 382655b5bb4SJoe Perches msg = filp->private_data; 3831da177e4SLinus Torvalds len += msg->len - msg->copied; 3841da177e4SLinus Torvalds } 385d0fe13baSStanislav Kinsbursky spin_unlock(&pipe->lock); 3862c9030eeSStanislav Kinsbursky mutex_unlock(&inode->i_mutex); 3871da177e4SLinus Torvalds return put_user(len, (int __user *)arg); 3881da177e4SLinus Torvalds default: 3891da177e4SLinus Torvalds return -EINVAL; 3901da177e4SLinus Torvalds } 3911da177e4SLinus Torvalds } 3921da177e4SLinus Torvalds 393da7071d7SArjan van de Ven static const struct file_operations rpc_pipe_fops = { 3941da177e4SLinus Torvalds .owner = THIS_MODULE, 3951da177e4SLinus Torvalds .llseek = no_llseek, 3961da177e4SLinus Torvalds .read = rpc_pipe_read, 3971da177e4SLinus Torvalds .write = rpc_pipe_write, 3981da177e4SLinus Torvalds .poll = rpc_pipe_poll, 399674b604cSFrederic Weisbecker .unlocked_ioctl = rpc_pipe_ioctl, 4001da177e4SLinus Torvalds .open = rpc_pipe_open, 4011da177e4SLinus Torvalds .release = rpc_pipe_release, 4021da177e4SLinus Torvalds }; 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds static int 4051da177e4SLinus Torvalds rpc_show_info(struct seq_file *m, void *v) 4061da177e4SLinus Torvalds { 4071da177e4SLinus Torvalds struct rpc_clnt *clnt = m->private; 4081da177e4SLinus Torvalds 4092446ab60STrond Myklebust rcu_read_lock(); 4104e0038b6STrond Myklebust seq_printf(m, "RPC server: %s\n", 4114e0038b6STrond Myklebust rcu_dereference(clnt->cl_xprt)->servername); 4121da177e4SLinus Torvalds seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, 4131da177e4SLinus Torvalds clnt->cl_prog, clnt->cl_vers); 414e7f78657SChuck Lever seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); 415e7f78657SChuck Lever seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); 416bf19aaceSJ. Bruce Fields seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); 4172446ab60STrond Myklebust rcu_read_unlock(); 4181da177e4SLinus Torvalds return 0; 4191da177e4SLinus Torvalds } 4201da177e4SLinus Torvalds 4211da177e4SLinus Torvalds static int 4221da177e4SLinus Torvalds rpc_info_open(struct inode *inode, struct file *file) 4231da177e4SLinus Torvalds { 424006abe88STrond Myklebust struct rpc_clnt *clnt = NULL; 4251da177e4SLinus Torvalds int ret = single_open(file, rpc_show_info, NULL); 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds if (!ret) { 4281da177e4SLinus Torvalds struct seq_file *m = file->private_data; 429006abe88STrond Myklebust 430006abe88STrond Myklebust spin_lock(&file->f_path.dentry->d_lock); 431006abe88STrond Myklebust if (!d_unhashed(file->f_path.dentry)) 4321da177e4SLinus Torvalds clnt = RPC_I(inode)->private; 433006abe88STrond Myklebust if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { 434006abe88STrond Myklebust spin_unlock(&file->f_path.dentry->d_lock); 4351da177e4SLinus Torvalds m->private = clnt; 4361da177e4SLinus Torvalds } else { 437006abe88STrond Myklebust spin_unlock(&file->f_path.dentry->d_lock); 4381da177e4SLinus Torvalds single_release(inode, file); 4391da177e4SLinus Torvalds ret = -EINVAL; 4401da177e4SLinus Torvalds } 4411da177e4SLinus Torvalds } 4421da177e4SLinus Torvalds return ret; 4431da177e4SLinus Torvalds } 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds static int 4461da177e4SLinus Torvalds rpc_info_release(struct inode *inode, struct file *file) 4471da177e4SLinus Torvalds { 4481da177e4SLinus Torvalds struct seq_file *m = file->private_data; 4491da177e4SLinus Torvalds struct rpc_clnt *clnt = (struct rpc_clnt *)m->private; 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds if (clnt) 4521da177e4SLinus Torvalds rpc_release_client(clnt); 4531da177e4SLinus Torvalds return single_release(inode, file); 4541da177e4SLinus Torvalds } 4551da177e4SLinus Torvalds 456da7071d7SArjan van de Ven static const struct file_operations rpc_info_operations = { 4571da177e4SLinus Torvalds .owner = THIS_MODULE, 4581da177e4SLinus Torvalds .open = rpc_info_open, 4591da177e4SLinus Torvalds .read = seq_read, 4601da177e4SLinus Torvalds .llseek = seq_lseek, 4611da177e4SLinus Torvalds .release = rpc_info_release, 4621da177e4SLinus Torvalds }; 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds /* 4661da177e4SLinus Torvalds * Description of fs contents. 4671da177e4SLinus Torvalds */ 4681da177e4SLinus Torvalds struct rpc_filelist { 469ac6feceeSTrond Myklebust const char *name; 47099ac48f5SArjan van de Ven const struct file_operations *i_fop; 4717364af6aSTrond Myklebust umode_t mode; 4721da177e4SLinus Torvalds }; 4731da177e4SLinus Torvalds 474fe15ce44SNick Piggin static int rpc_delete_dentry(const struct dentry *dentry) 47562e1761cSTrond Myklebust { 47662e1761cSTrond Myklebust return 1; 47762e1761cSTrond Myklebust } 47862e1761cSTrond Myklebust 4793ba13d17SAl Viro static const struct dentry_operations rpc_dentry_operations = { 48062e1761cSTrond Myklebust .d_delete = rpc_delete_dentry, 48162e1761cSTrond Myklebust }; 48262e1761cSTrond Myklebust 4831da177e4SLinus Torvalds static struct inode * 4847364af6aSTrond Myklebust rpc_get_inode(struct super_block *sb, umode_t mode) 4851da177e4SLinus Torvalds { 4861da177e4SLinus Torvalds struct inode *inode = new_inode(sb); 4871da177e4SLinus Torvalds if (!inode) 4881da177e4SLinus Torvalds return NULL; 48985fe4025SChristoph Hellwig inode->i_ino = get_next_ino(); 4901da177e4SLinus Torvalds inode->i_mode = mode; 4911da177e4SLinus Torvalds inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 4921da177e4SLinus Torvalds switch (mode & S_IFMT) { 4931da177e4SLinus Torvalds case S_IFDIR: 4941da177e4SLinus Torvalds inode->i_fop = &simple_dir_operations; 4951da177e4SLinus Torvalds inode->i_op = &simple_dir_inode_operations; 496d8c76e6fSDave Hansen inc_nlink(inode); 4971da177e4SLinus Torvalds default: 4981da177e4SLinus Torvalds break; 4991da177e4SLinus Torvalds } 5001da177e4SLinus Torvalds return inode; 5011da177e4SLinus Torvalds } 5021da177e4SLinus Torvalds 5037589806eSTrond Myklebust static int __rpc_create_common(struct inode *dir, struct dentry *dentry, 5047589806eSTrond Myklebust umode_t mode, 5057589806eSTrond Myklebust const struct file_operations *i_fop, 5067589806eSTrond Myklebust void *private) 5077589806eSTrond Myklebust { 5087589806eSTrond Myklebust struct inode *inode; 5097589806eSTrond Myklebust 510beb0f0a9STrond Myklebust d_drop(dentry); 5117589806eSTrond Myklebust inode = rpc_get_inode(dir->i_sb, mode); 5127589806eSTrond Myklebust if (!inode) 5137589806eSTrond Myklebust goto out_err; 5147589806eSTrond Myklebust inode->i_ino = iunique(dir->i_sb, 100); 5157589806eSTrond Myklebust if (i_fop) 5167589806eSTrond Myklebust inode->i_fop = i_fop; 5177589806eSTrond Myklebust if (private) 5187589806eSTrond Myklebust rpc_inode_setowner(inode, private); 5197589806eSTrond Myklebust d_add(dentry, inode); 5207589806eSTrond Myklebust return 0; 5217589806eSTrond Myklebust out_err: 5227589806eSTrond Myklebust printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", 5237589806eSTrond Myklebust __FILE__, __func__, dentry->d_name.name); 5247589806eSTrond Myklebust dput(dentry); 5257589806eSTrond Myklebust return -ENOMEM; 5267589806eSTrond Myklebust } 5277589806eSTrond Myklebust 528ac6feceeSTrond Myklebust static int __rpc_create(struct inode *dir, struct dentry *dentry, 529ac6feceeSTrond Myklebust umode_t mode, 530ac6feceeSTrond Myklebust const struct file_operations *i_fop, 531ac6feceeSTrond Myklebust void *private) 532ac6feceeSTrond Myklebust { 533ac6feceeSTrond Myklebust int err; 534ac6feceeSTrond Myklebust 535ac6feceeSTrond Myklebust err = __rpc_create_common(dir, dentry, S_IFREG | mode, i_fop, private); 536ac6feceeSTrond Myklebust if (err) 537ac6feceeSTrond Myklebust return err; 538ac6feceeSTrond Myklebust fsnotify_create(dir, dentry); 539ac6feceeSTrond Myklebust return 0; 540ac6feceeSTrond Myklebust } 541ac6feceeSTrond Myklebust 5427589806eSTrond Myklebust static int __rpc_mkdir(struct inode *dir, struct dentry *dentry, 5437589806eSTrond Myklebust umode_t mode, 5447589806eSTrond Myklebust const struct file_operations *i_fop, 5457589806eSTrond Myklebust void *private) 5467589806eSTrond Myklebust { 5477589806eSTrond Myklebust int err; 5487589806eSTrond Myklebust 5497589806eSTrond Myklebust err = __rpc_create_common(dir, dentry, S_IFDIR | mode, i_fop, private); 5507589806eSTrond Myklebust if (err) 5517589806eSTrond Myklebust return err; 5527589806eSTrond Myklebust inc_nlink(dir); 5537589806eSTrond Myklebust fsnotify_mkdir(dir, dentry); 5547589806eSTrond Myklebust return 0; 5557589806eSTrond Myklebust } 5567589806eSTrond Myklebust 557ba9e0975SStanislav Kinsbursky static void 558ba9e0975SStanislav Kinsbursky init_pipe(struct rpc_pipe *pipe) 559ba9e0975SStanislav Kinsbursky { 560ba9e0975SStanislav Kinsbursky pipe->nreaders = 0; 561ba9e0975SStanislav Kinsbursky pipe->nwriters = 0; 562ba9e0975SStanislav Kinsbursky INIT_LIST_HEAD(&pipe->in_upcall); 563ba9e0975SStanislav Kinsbursky INIT_LIST_HEAD(&pipe->in_downcall); 564ba9e0975SStanislav Kinsbursky INIT_LIST_HEAD(&pipe->pipe); 565ba9e0975SStanislav Kinsbursky pipe->pipelen = 0; 566ba9e0975SStanislav Kinsbursky INIT_DELAYED_WORK(&pipe->queue_timeout, 567ba9e0975SStanislav Kinsbursky rpc_timeout_upcall_queue); 568ba9e0975SStanislav Kinsbursky pipe->ops = NULL; 569ba9e0975SStanislav Kinsbursky spin_lock_init(&pipe->lock); 570c239d83bSStanislav Kinsbursky pipe->dentry = NULL; 571ba9e0975SStanislav Kinsbursky } 572ba9e0975SStanislav Kinsbursky 573c239d83bSStanislav Kinsbursky void rpc_destroy_pipe_data(struct rpc_pipe *pipe) 574c239d83bSStanislav Kinsbursky { 575c239d83bSStanislav Kinsbursky kfree(pipe); 576c239d83bSStanislav Kinsbursky } 577c239d83bSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_destroy_pipe_data); 578c239d83bSStanislav Kinsbursky 579c239d83bSStanislav Kinsbursky struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags) 5807589806eSTrond Myklebust { 581ba9e0975SStanislav Kinsbursky struct rpc_pipe *pipe; 5827589806eSTrond Myklebust 583ba9e0975SStanislav Kinsbursky pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL); 584ba9e0975SStanislav Kinsbursky if (!pipe) 585c239d83bSStanislav Kinsbursky return ERR_PTR(-ENOMEM); 586ba9e0975SStanislav Kinsbursky init_pipe(pipe); 587c239d83bSStanislav Kinsbursky pipe->ops = ops; 588c239d83bSStanislav Kinsbursky pipe->flags = flags; 589c239d83bSStanislav Kinsbursky return pipe; 590ba9e0975SStanislav Kinsbursky } 591c239d83bSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_mkpipe_data); 592c239d83bSStanislav Kinsbursky 593c239d83bSStanislav Kinsbursky static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry, 5947589806eSTrond Myklebust umode_t mode, 5957589806eSTrond Myklebust const struct file_operations *i_fop, 5967589806eSTrond Myklebust void *private, 597c239d83bSStanislav Kinsbursky struct rpc_pipe *pipe) 5987589806eSTrond Myklebust { 5997589806eSTrond Myklebust struct rpc_inode *rpci; 6007589806eSTrond Myklebust int err; 6017589806eSTrond Myklebust 6027589806eSTrond Myklebust err = __rpc_create_common(dir, dentry, S_IFIFO | mode, i_fop, private); 6037589806eSTrond Myklebust if (err) 6047589806eSTrond Myklebust return err; 6057589806eSTrond Myklebust rpci = RPC_I(dentry->d_inode); 6067589806eSTrond Myklebust rpci->private = private; 607ba9e0975SStanislav Kinsbursky rpci->pipe = pipe; 6087589806eSTrond Myklebust fsnotify_create(dir, dentry); 6097589806eSTrond Myklebust return 0; 6107589806eSTrond Myklebust } 6117589806eSTrond Myklebust 612ac6feceeSTrond Myklebust static int __rpc_rmdir(struct inode *dir, struct dentry *dentry) 613ac6feceeSTrond Myklebust { 614ac6feceeSTrond Myklebust int ret; 615ac6feceeSTrond Myklebust 616ac6feceeSTrond Myklebust dget(dentry); 617ac6feceeSTrond Myklebust ret = simple_rmdir(dir, dentry); 618ac6feceeSTrond Myklebust d_delete(dentry); 619ac6feceeSTrond Myklebust dput(dentry); 620ac6feceeSTrond Myklebust return ret; 621ac6feceeSTrond Myklebust } 622ac6feceeSTrond Myklebust 623eee17325SStanislav Kinsbursky int rpc_rmdir(struct dentry *dentry) 624eee17325SStanislav Kinsbursky { 625eee17325SStanislav Kinsbursky struct dentry *parent; 626eee17325SStanislav Kinsbursky struct inode *dir; 627eee17325SStanislav Kinsbursky int error; 628eee17325SStanislav Kinsbursky 629eee17325SStanislav Kinsbursky parent = dget_parent(dentry); 630eee17325SStanislav Kinsbursky dir = parent->d_inode; 631eee17325SStanislav Kinsbursky mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 632eee17325SStanislav Kinsbursky error = __rpc_rmdir(dir, dentry); 633eee17325SStanislav Kinsbursky mutex_unlock(&dir->i_mutex); 634eee17325SStanislav Kinsbursky dput(parent); 635eee17325SStanislav Kinsbursky return error; 636eee17325SStanislav Kinsbursky } 637eee17325SStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_rmdir); 638eee17325SStanislav Kinsbursky 639810d90bcSTrond Myklebust static int __rpc_unlink(struct inode *dir, struct dentry *dentry) 640810d90bcSTrond Myklebust { 641810d90bcSTrond Myklebust int ret; 642810d90bcSTrond Myklebust 643810d90bcSTrond Myklebust dget(dentry); 644810d90bcSTrond Myklebust ret = simple_unlink(dir, dentry); 645810d90bcSTrond Myklebust d_delete(dentry); 646810d90bcSTrond Myklebust dput(dentry); 647810d90bcSTrond Myklebust return ret; 648810d90bcSTrond Myklebust } 649810d90bcSTrond Myklebust 650810d90bcSTrond Myklebust static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry) 651810d90bcSTrond Myklebust { 652810d90bcSTrond Myklebust struct inode *inode = dentry->d_inode; 653810d90bcSTrond Myklebust 654810d90bcSTrond Myklebust rpc_close_pipes(inode); 655810d90bcSTrond Myklebust return __rpc_unlink(dir, dentry); 656810d90bcSTrond Myklebust } 657810d90bcSTrond Myklebust 658cfeaa4a3STrond Myklebust static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, 659cfeaa4a3STrond Myklebust struct qstr *name) 660cfeaa4a3STrond Myklebust { 661cfeaa4a3STrond Myklebust struct dentry *dentry; 662cfeaa4a3STrond Myklebust 6635bff0386SStanislav Kinsbursky dentry = d_lookup(parent, name); 6645bff0386SStanislav Kinsbursky if (!dentry) { 6655bff0386SStanislav Kinsbursky dentry = d_alloc(parent, name); 6665bff0386SStanislav Kinsbursky if (!dentry) 6675bff0386SStanislav Kinsbursky return ERR_PTR(-ENOMEM); 6685bff0386SStanislav Kinsbursky } 6695bff0386SStanislav Kinsbursky if (dentry->d_inode == NULL) { 670e401452dSJeff Layton if (!dentry->d_op) 6715bff0386SStanislav Kinsbursky d_set_d_op(dentry, &rpc_dentry_operations); 672f1f0abe1SDan Carpenter return dentry; 6735bff0386SStanislav Kinsbursky } 674cfeaa4a3STrond Myklebust dput(dentry); 675cfeaa4a3STrond Myklebust return ERR_PTR(-EEXIST); 676cfeaa4a3STrond Myklebust } 677cfeaa4a3STrond Myklebust 6781da177e4SLinus Torvalds /* 6791da177e4SLinus Torvalds * FIXME: This probably has races. 6801da177e4SLinus Torvalds */ 681ac6feceeSTrond Myklebust static void __rpc_depopulate(struct dentry *parent, 682ac6feceeSTrond Myklebust const struct rpc_filelist *files, 683ac6feceeSTrond Myklebust int start, int eof) 6841da177e4SLinus Torvalds { 6851da177e4SLinus Torvalds struct inode *dir = parent->d_inode; 686ac6feceeSTrond Myklebust struct dentry *dentry; 687ac6feceeSTrond Myklebust struct qstr name; 688ac6feceeSTrond Myklebust int i; 689ac6feceeSTrond Myklebust 690ac6feceeSTrond Myklebust for (i = start; i < eof; i++) { 691ac6feceeSTrond Myklebust name.name = files[i].name; 692ac6feceeSTrond Myklebust name.len = strlen(files[i].name); 693ac6feceeSTrond Myklebust name.hash = full_name_hash(name.name, name.len); 694ac6feceeSTrond Myklebust dentry = d_lookup(parent, &name); 695ac6feceeSTrond Myklebust 696ac6feceeSTrond Myklebust if (dentry == NULL) 697ac6feceeSTrond Myklebust continue; 698ac6feceeSTrond Myklebust if (dentry->d_inode == NULL) 699ac6feceeSTrond Myklebust goto next; 700ac6feceeSTrond Myklebust switch (dentry->d_inode->i_mode & S_IFMT) { 701ac6feceeSTrond Myklebust default: 702ac6feceeSTrond Myklebust BUG(); 703ac6feceeSTrond Myklebust case S_IFREG: 704ac6feceeSTrond Myklebust __rpc_unlink(dir, dentry); 705ac6feceeSTrond Myklebust break; 706ac6feceeSTrond Myklebust case S_IFDIR: 707ac6feceeSTrond Myklebust __rpc_rmdir(dir, dentry); 708ac6feceeSTrond Myklebust } 709ac6feceeSTrond Myklebust next: 710ac6feceeSTrond Myklebust dput(dentry); 711ac6feceeSTrond Myklebust } 712ac6feceeSTrond Myklebust } 713ac6feceeSTrond Myklebust 714ac6feceeSTrond Myklebust static void rpc_depopulate(struct dentry *parent, 715ac6feceeSTrond Myklebust const struct rpc_filelist *files, 716ac6feceeSTrond Myklebust int start, int eof) 717ac6feceeSTrond Myklebust { 718ac6feceeSTrond Myklebust struct inode *dir = parent->d_inode; 7191da177e4SLinus Torvalds 720c6573c29SArjan van de Ven mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD); 721ac6feceeSTrond Myklebust __rpc_depopulate(parent, files, start, eof); 7221b1dcc1bSJes Sorensen mutex_unlock(&dir->i_mutex); 7231da177e4SLinus Torvalds } 7241da177e4SLinus Torvalds 725ac6feceeSTrond Myklebust static int rpc_populate(struct dentry *parent, 726ac6feceeSTrond Myklebust const struct rpc_filelist *files, 727ac6feceeSTrond Myklebust int start, int eof, 728ac6feceeSTrond Myklebust void *private) 7291da177e4SLinus Torvalds { 730ac6feceeSTrond Myklebust struct inode *dir = parent->d_inode; 7311da177e4SLinus Torvalds struct dentry *dentry; 732ac6feceeSTrond Myklebust int i, err; 7331da177e4SLinus Torvalds 7341b1dcc1bSJes Sorensen mutex_lock(&dir->i_mutex); 7351da177e4SLinus Torvalds for (i = start; i < eof; i++) { 736ac6feceeSTrond Myklebust struct qstr q; 737ac6feceeSTrond Myklebust 738ac6feceeSTrond Myklebust q.name = files[i].name; 739ac6feceeSTrond Myklebust q.len = strlen(files[i].name); 740ac6feceeSTrond Myklebust q.hash = full_name_hash(q.name, q.len); 741ac6feceeSTrond Myklebust dentry = __rpc_lookup_create_exclusive(parent, &q); 742ac6feceeSTrond Myklebust err = PTR_ERR(dentry); 743ac6feceeSTrond Myklebust if (IS_ERR(dentry)) 7441da177e4SLinus Torvalds goto out_bad; 745ac6feceeSTrond Myklebust switch (files[i].mode & S_IFMT) { 746ac6feceeSTrond Myklebust default: 747ac6feceeSTrond Myklebust BUG(); 748ac6feceeSTrond Myklebust case S_IFREG: 749ac6feceeSTrond Myklebust err = __rpc_create(dir, dentry, 750ac6feceeSTrond Myklebust files[i].mode, 751ac6feceeSTrond Myklebust files[i].i_fop, 752ac6feceeSTrond Myklebust private); 753ac6feceeSTrond Myklebust break; 754ac6feceeSTrond Myklebust case S_IFDIR: 755ac6feceeSTrond Myklebust err = __rpc_mkdir(dir, dentry, 756ac6feceeSTrond Myklebust files[i].mode, 757ac6feceeSTrond Myklebust NULL, 758ac6feceeSTrond Myklebust private); 7591da177e4SLinus Torvalds } 760ac6feceeSTrond Myklebust if (err != 0) 761ac6feceeSTrond Myklebust goto out_bad; 7621da177e4SLinus Torvalds } 7631b1dcc1bSJes Sorensen mutex_unlock(&dir->i_mutex); 7641da177e4SLinus Torvalds return 0; 7651da177e4SLinus Torvalds out_bad: 766ac6feceeSTrond Myklebust __rpc_depopulate(parent, files, start, eof); 7671b1dcc1bSJes Sorensen mutex_unlock(&dir->i_mutex); 7681da177e4SLinus Torvalds printk(KERN_WARNING "%s: %s failed to populate directory %s\n", 7690dc47877SHarvey Harrison __FILE__, __func__, parent->d_name.name); 770ac6feceeSTrond Myklebust return err; 771f134585aSTrond Myklebust } 772f134585aSTrond Myklebust 773e57aed77STrond Myklebust static struct dentry *rpc_mkdir_populate(struct dentry *parent, 774e57aed77STrond Myklebust struct qstr *name, umode_t mode, void *private, 775e57aed77STrond Myklebust int (*populate)(struct dentry *, void *), void *args_populate) 776f134585aSTrond Myklebust { 777f134585aSTrond Myklebust struct dentry *dentry; 7787d59d1e8STrond Myklebust struct inode *dir = parent->d_inode; 779f134585aSTrond Myklebust int error; 780f134585aSTrond Myklebust 7817d59d1e8STrond Myklebust mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 7827d59d1e8STrond Myklebust dentry = __rpc_lookup_create_exclusive(parent, name); 783f134585aSTrond Myklebust if (IS_ERR(dentry)) 7847d59d1e8STrond Myklebust goto out; 7857d59d1e8STrond Myklebust error = __rpc_mkdir(dir, dentry, mode, NULL, private); 7867589806eSTrond Myklebust if (error != 0) 7877589806eSTrond Myklebust goto out_err; 788e57aed77STrond Myklebust if (populate != NULL) { 789e57aed77STrond Myklebust error = populate(dentry, args_populate); 790f134585aSTrond Myklebust if (error) 791ac6feceeSTrond Myklebust goto err_rmdir; 792e57aed77STrond Myklebust } 793f134585aSTrond Myklebust out: 7941b1dcc1bSJes Sorensen mutex_unlock(&dir->i_mutex); 7955c3e985aSTrond Myklebust return dentry; 796ac6feceeSTrond Myklebust err_rmdir: 797f134585aSTrond Myklebust __rpc_rmdir(dir, dentry); 7987589806eSTrond Myklebust out_err: 799f134585aSTrond Myklebust dentry = ERR_PTR(error); 800f134585aSTrond Myklebust goto out; 801f134585aSTrond Myklebust } 802f134585aSTrond Myklebust 803e57aed77STrond Myklebust static int rpc_rmdir_depopulate(struct dentry *dentry, 804e57aed77STrond Myklebust void (*depopulate)(struct dentry *)) 805f134585aSTrond Myklebust { 806dff02cc1STrond Myklebust struct dentry *parent; 807f134585aSTrond Myklebust struct inode *dir; 808f134585aSTrond Myklebust int error; 809f134585aSTrond Myklebust 810dff02cc1STrond Myklebust parent = dget_parent(dentry); 811dff02cc1STrond Myklebust dir = parent->d_inode; 812c6573c29SArjan van de Ven mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 813e57aed77STrond Myklebust if (depopulate != NULL) 814e57aed77STrond Myklebust depopulate(dentry); 815f134585aSTrond Myklebust error = __rpc_rmdir(dir, dentry); 8161b1dcc1bSJes Sorensen mutex_unlock(&dir->i_mutex); 817dff02cc1STrond Myklebust dput(parent); 818f134585aSTrond Myklebust return error; 819f134585aSTrond Myklebust } 8201da177e4SLinus Torvalds 82193a44a75SJ. Bruce Fields /** 82293a44a75SJ. Bruce Fields * rpc_mkpipe - make an rpc_pipefs file for kernel<->userspace communication 82393a44a75SJ. Bruce Fields * @parent: dentry of directory to create new "pipe" in 82493a44a75SJ. Bruce Fields * @name: name of pipe 82593a44a75SJ. Bruce Fields * @private: private data to associate with the pipe, for the caller's use 826bda14606SRandy Dunlap * @pipe: &rpc_pipe containing input parameters 82793a44a75SJ. Bruce Fields * 82893a44a75SJ. Bruce Fields * Data is made available for userspace to read by calls to 82993a44a75SJ. Bruce Fields * rpc_queue_upcall(). The actual reads will result in calls to 83093a44a75SJ. Bruce Fields * @ops->upcall, which will be called with the file pointer, 83193a44a75SJ. Bruce Fields * message, and userspace buffer to copy to. 83293a44a75SJ. Bruce Fields * 83393a44a75SJ. Bruce Fields * Writes can come at any time, and do not necessarily have to be 83493a44a75SJ. Bruce Fields * responses to upcalls. They will result in calls to @msg->downcall. 83593a44a75SJ. Bruce Fields * 83693a44a75SJ. Bruce Fields * The @private argument passed here will be available to all these methods 837496ad9aaSAl Viro * from the file pointer, via RPC_I(file_inode(file))->private. 83893a44a75SJ. Bruce Fields */ 839c239d83bSStanislav Kinsbursky struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, 840c239d83bSStanislav Kinsbursky void *private, struct rpc_pipe *pipe) 8411da177e4SLinus Torvalds { 8421da177e4SLinus Torvalds struct dentry *dentry; 8437589806eSTrond Myklebust struct inode *dir = parent->d_inode; 8447364af6aSTrond Myklebust umode_t umode = S_IFIFO | S_IRUSR | S_IWUSR; 845cfeaa4a3STrond Myklebust struct qstr q; 8467589806eSTrond Myklebust int err; 8477364af6aSTrond Myklebust 848c239d83bSStanislav Kinsbursky if (pipe->ops->upcall == NULL) 8497364af6aSTrond Myklebust umode &= ~S_IRUGO; 850c239d83bSStanislav Kinsbursky if (pipe->ops->downcall == NULL) 8517364af6aSTrond Myklebust umode &= ~S_IWUGO; 8521da177e4SLinus Torvalds 853cfeaa4a3STrond Myklebust q.name = name; 854cfeaa4a3STrond Myklebust q.len = strlen(name); 855cfeaa4a3STrond Myklebust q.hash = full_name_hash(q.name, q.len), 856cfeaa4a3STrond Myklebust 857cfeaa4a3STrond Myklebust mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 8585bff0386SStanislav Kinsbursky dentry = __rpc_lookup_create_exclusive(parent, &q); 8591da177e4SLinus Torvalds if (IS_ERR(dentry)) 860cfeaa4a3STrond Myklebust goto out; 861c239d83bSStanislav Kinsbursky err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops, 862c239d83bSStanislav Kinsbursky private, pipe); 8637589806eSTrond Myklebust if (err) 8647589806eSTrond Myklebust goto out_err; 865f134585aSTrond Myklebust out: 8661b1dcc1bSJes Sorensen mutex_unlock(&dir->i_mutex); 8675c3e985aSTrond Myklebust return dentry; 8687589806eSTrond Myklebust out_err: 8697589806eSTrond Myklebust dentry = ERR_PTR(err); 870158998b6STrond Myklebust printk(KERN_WARNING "%s: %s() failed to create pipe %s/%s (errno = %d)\n", 8710dc47877SHarvey Harrison __FILE__, __func__, parent->d_name.name, name, 8727589806eSTrond Myklebust err); 873f134585aSTrond Myklebust goto out; 8741da177e4SLinus Torvalds } 875c239d83bSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry); 8761da177e4SLinus Torvalds 87793a44a75SJ. Bruce Fields /** 87893a44a75SJ. Bruce Fields * rpc_unlink - remove a pipe 87993a44a75SJ. Bruce Fields * @dentry: dentry for the pipe, as returned from rpc_mkpipe 88093a44a75SJ. Bruce Fields * 88193a44a75SJ. Bruce Fields * After this call, lookups will no longer find the pipe, and any 88293a44a75SJ. Bruce Fields * attempts to read or write using preexisting opens of the pipe will 88393a44a75SJ. Bruce Fields * return -EPIPE. 88493a44a75SJ. Bruce Fields */ 885f134585aSTrond Myklebust int 8865d67476fSTrond Myklebust rpc_unlink(struct dentry *dentry) 8871da177e4SLinus Torvalds { 8885d67476fSTrond Myklebust struct dentry *parent; 889f134585aSTrond Myklebust struct inode *dir; 8905d67476fSTrond Myklebust int error = 0; 8911da177e4SLinus Torvalds 8925d67476fSTrond Myklebust parent = dget_parent(dentry); 8935d67476fSTrond Myklebust dir = parent->d_inode; 894c6573c29SArjan van de Ven mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 895810d90bcSTrond Myklebust error = __rpc_rmpipe(dir, dentry); 8961b1dcc1bSJes Sorensen mutex_unlock(&dir->i_mutex); 8975d67476fSTrond Myklebust dput(parent); 898f134585aSTrond Myklebust return error; 8991da177e4SLinus Torvalds } 900468039eeSTrond Myklebust EXPORT_SYMBOL_GPL(rpc_unlink); 9011da177e4SLinus Torvalds 902e57aed77STrond Myklebust enum { 903e57aed77STrond Myklebust RPCAUTH_info, 904e57aed77STrond Myklebust RPCAUTH_EOF 905e57aed77STrond Myklebust }; 906e57aed77STrond Myklebust 907e57aed77STrond Myklebust static const struct rpc_filelist authfiles[] = { 908e57aed77STrond Myklebust [RPCAUTH_info] = { 909e57aed77STrond Myklebust .name = "info", 910e57aed77STrond Myklebust .i_fop = &rpc_info_operations, 911e57aed77STrond Myklebust .mode = S_IFREG | S_IRUSR, 912e57aed77STrond Myklebust }, 913e57aed77STrond Myklebust }; 914e57aed77STrond Myklebust 915e57aed77STrond Myklebust static int rpc_clntdir_populate(struct dentry *dentry, void *private) 916e57aed77STrond Myklebust { 917e57aed77STrond Myklebust return rpc_populate(dentry, 918e57aed77STrond Myklebust authfiles, RPCAUTH_info, RPCAUTH_EOF, 919e57aed77STrond Myklebust private); 920e57aed77STrond Myklebust } 921e57aed77STrond Myklebust 922e57aed77STrond Myklebust static void rpc_clntdir_depopulate(struct dentry *dentry) 923e57aed77STrond Myklebust { 924e57aed77STrond Myklebust rpc_depopulate(dentry, authfiles, RPCAUTH_info, RPCAUTH_EOF); 925e57aed77STrond Myklebust } 926e57aed77STrond Myklebust 9277d59d1e8STrond Myklebust /** 9287d59d1e8STrond Myklebust * rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs 9294111d4fdSRandy Dunlap * @dentry: dentry from the rpc_pipefs root to the new directory 9304111d4fdSRandy Dunlap * @name: &struct qstr for the name 9317d59d1e8STrond Myklebust * @rpc_client: rpc client to associate with this directory 9327d59d1e8STrond Myklebust * 9337d59d1e8STrond Myklebust * This creates a directory at the given @path associated with 9347d59d1e8STrond Myklebust * @rpc_clnt, which will contain a file named "info" with some basic 9357d59d1e8STrond Myklebust * information about the client, together with any "pipes" that may 9367d59d1e8STrond Myklebust * later be created using rpc_mkpipe(). 9377d59d1e8STrond Myklebust */ 93823ac6581STrond Myklebust struct dentry *rpc_create_client_dir(struct dentry *dentry, 93923ac6581STrond Myklebust struct qstr *name, 9407d59d1e8STrond Myklebust struct rpc_clnt *rpc_client) 9417d59d1e8STrond Myklebust { 942e57aed77STrond Myklebust return rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, 943e57aed77STrond Myklebust rpc_clntdir_populate, rpc_client); 944e57aed77STrond Myklebust } 945e57aed77STrond Myklebust 946e57aed77STrond Myklebust /** 947e57aed77STrond Myklebust * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() 948bda14606SRandy Dunlap * @dentry: dentry for the pipe 949e57aed77STrond Myklebust */ 950e57aed77STrond Myklebust int rpc_remove_client_dir(struct dentry *dentry) 951e57aed77STrond Myklebust { 952e57aed77STrond Myklebust return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate); 9537d59d1e8STrond Myklebust } 9547d59d1e8STrond Myklebust 9558854e82dSTrond Myklebust static const struct rpc_filelist cache_pipefs_files[3] = { 9568854e82dSTrond Myklebust [0] = { 9578854e82dSTrond Myklebust .name = "channel", 9588854e82dSTrond Myklebust .i_fop = &cache_file_operations_pipefs, 95996c61cbdSTrond Myklebust .mode = S_IFREG|S_IRUSR|S_IWUSR, 9608854e82dSTrond Myklebust }, 9618854e82dSTrond Myklebust [1] = { 9628854e82dSTrond Myklebust .name = "content", 9638854e82dSTrond Myklebust .i_fop = &content_file_operations_pipefs, 9648854e82dSTrond Myklebust .mode = S_IFREG|S_IRUSR, 9658854e82dSTrond Myklebust }, 9668854e82dSTrond Myklebust [2] = { 9678854e82dSTrond Myklebust .name = "flush", 9688854e82dSTrond Myklebust .i_fop = &cache_flush_operations_pipefs, 9698854e82dSTrond Myklebust .mode = S_IFREG|S_IRUSR|S_IWUSR, 9708854e82dSTrond Myklebust }, 9718854e82dSTrond Myklebust }; 9728854e82dSTrond Myklebust 9738854e82dSTrond Myklebust static int rpc_cachedir_populate(struct dentry *dentry, void *private) 9748854e82dSTrond Myklebust { 9758854e82dSTrond Myklebust return rpc_populate(dentry, 9768854e82dSTrond Myklebust cache_pipefs_files, 0, 3, 9778854e82dSTrond Myklebust private); 9788854e82dSTrond Myklebust } 9798854e82dSTrond Myklebust 9808854e82dSTrond Myklebust static void rpc_cachedir_depopulate(struct dentry *dentry) 9818854e82dSTrond Myklebust { 9828854e82dSTrond Myklebust rpc_depopulate(dentry, cache_pipefs_files, 0, 3); 9838854e82dSTrond Myklebust } 9848854e82dSTrond Myklebust 9858854e82dSTrond Myklebust struct dentry *rpc_create_cache_dir(struct dentry *parent, struct qstr *name, 98664f1426fSAl Viro umode_t umode, struct cache_detail *cd) 9878854e82dSTrond Myklebust { 9888854e82dSTrond Myklebust return rpc_mkdir_populate(parent, name, umode, NULL, 9898854e82dSTrond Myklebust rpc_cachedir_populate, cd); 9908854e82dSTrond Myklebust } 9918854e82dSTrond Myklebust 9928854e82dSTrond Myklebust void rpc_remove_cache_dir(struct dentry *dentry) 9938854e82dSTrond Myklebust { 9948854e82dSTrond Myklebust rpc_rmdir_depopulate(dentry, rpc_cachedir_depopulate); 9958854e82dSTrond Myklebust } 9968854e82dSTrond Myklebust 9971da177e4SLinus Torvalds /* 9981da177e4SLinus Torvalds * populate the filesystem 9991da177e4SLinus Torvalds */ 1000b87221deSAlexey Dobriyan static const struct super_operations s_ops = { 10011da177e4SLinus Torvalds .alloc_inode = rpc_alloc_inode, 10021da177e4SLinus Torvalds .destroy_inode = rpc_destroy_inode, 10031da177e4SLinus Torvalds .statfs = simple_statfs, 10041da177e4SLinus Torvalds }; 10051da177e4SLinus Torvalds 10061da177e4SLinus Torvalds #define RPCAUTH_GSSMAGIC 0x67596969 10071da177e4SLinus Torvalds 1008bb156749STrond Myklebust /* 1009bb156749STrond Myklebust * We have a single directory with 1 node in it. 1010bb156749STrond Myklebust */ 1011bb156749STrond Myklebust enum { 1012bb156749STrond Myklebust RPCAUTH_lockd, 1013bb156749STrond Myklebust RPCAUTH_mount, 1014bb156749STrond Myklebust RPCAUTH_nfs, 1015bb156749STrond Myklebust RPCAUTH_portmap, 1016bb156749STrond Myklebust RPCAUTH_statd, 1017bb156749STrond Myklebust RPCAUTH_nfsd4_cb, 1018e571cbf1STrond Myklebust RPCAUTH_cache, 1019b3537c35SJeff Layton RPCAUTH_nfsd, 1020bb156749STrond Myklebust RPCAUTH_RootEOF 1021bb156749STrond Myklebust }; 1022bb156749STrond Myklebust 1023bb156749STrond Myklebust static const struct rpc_filelist files[] = { 1024bb156749STrond Myklebust [RPCAUTH_lockd] = { 1025bb156749STrond Myklebust .name = "lockd", 1026bb156749STrond Myklebust .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1027bb156749STrond Myklebust }, 1028bb156749STrond Myklebust [RPCAUTH_mount] = { 1029bb156749STrond Myklebust .name = "mount", 1030bb156749STrond Myklebust .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1031bb156749STrond Myklebust }, 1032bb156749STrond Myklebust [RPCAUTH_nfs] = { 1033bb156749STrond Myklebust .name = "nfs", 1034bb156749STrond Myklebust .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1035bb156749STrond Myklebust }, 1036bb156749STrond Myklebust [RPCAUTH_portmap] = { 1037bb156749STrond Myklebust .name = "portmap", 1038bb156749STrond Myklebust .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1039bb156749STrond Myklebust }, 1040bb156749STrond Myklebust [RPCAUTH_statd] = { 1041bb156749STrond Myklebust .name = "statd", 1042bb156749STrond Myklebust .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1043bb156749STrond Myklebust }, 1044bb156749STrond Myklebust [RPCAUTH_nfsd4_cb] = { 1045bb156749STrond Myklebust .name = "nfsd4_cb", 1046bb156749STrond Myklebust .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1047bb156749STrond Myklebust }, 1048e571cbf1STrond Myklebust [RPCAUTH_cache] = { 1049e571cbf1STrond Myklebust .name = "cache", 1050e571cbf1STrond Myklebust .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1051e571cbf1STrond Myklebust }, 1052b3537c35SJeff Layton [RPCAUTH_nfsd] = { 1053b3537c35SJeff Layton .name = "nfsd", 1054b3537c35SJeff Layton .mode = S_IFDIR | S_IRUGO | S_IXUGO, 1055b3537c35SJeff Layton }, 1056bb156749STrond Myklebust }; 1057bb156749STrond Myklebust 1058432eb1a5SStanislav Kinsbursky /* 1059432eb1a5SStanislav Kinsbursky * This call can be used only in RPC pipefs mount notification hooks. 1060432eb1a5SStanislav Kinsbursky */ 1061432eb1a5SStanislav Kinsbursky struct dentry *rpc_d_lookup_sb(const struct super_block *sb, 1062432eb1a5SStanislav Kinsbursky const unsigned char *dir_name) 1063432eb1a5SStanislav Kinsbursky { 106426fe5750SLinus Torvalds struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name)); 1065432eb1a5SStanislav Kinsbursky 106626fe5750SLinus Torvalds dir.hash = full_name_hash(dir.name, dir.len); 1067432eb1a5SStanislav Kinsbursky return d_lookup(sb->s_root, &dir); 1068432eb1a5SStanislav Kinsbursky } 1069432eb1a5SStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); 1070432eb1a5SStanislav Kinsbursky 1071c21a588fSStanislav Kinsbursky void rpc_pipefs_init_net(struct net *net) 1072c21a588fSStanislav Kinsbursky { 1073c21a588fSStanislav Kinsbursky struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1074c21a588fSStanislav Kinsbursky 1075c21a588fSStanislav Kinsbursky mutex_init(&sn->pipefs_sb_lock); 1076abfdbd53STrond Myklebust sn->gssd_running = 1; 10772aed8b47STrond Myklebust sn->pipe_version = -1; 1078c21a588fSStanislav Kinsbursky } 1079c21a588fSStanislav Kinsbursky 1080c21a588fSStanislav Kinsbursky /* 1081c21a588fSStanislav Kinsbursky * This call will be used for per network namespace operations calls. 1082c21a588fSStanislav Kinsbursky * Note: Function will be returned with pipefs_sb_lock taken if superblock was 1083c21a588fSStanislav Kinsbursky * found. This lock have to be released by rpc_put_sb_net() when all operations 1084c21a588fSStanislav Kinsbursky * will be completed. 1085c21a588fSStanislav Kinsbursky */ 1086c21a588fSStanislav Kinsbursky struct super_block *rpc_get_sb_net(const struct net *net) 1087c21a588fSStanislav Kinsbursky { 1088c21a588fSStanislav Kinsbursky struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1089c21a588fSStanislav Kinsbursky 1090c21a588fSStanislav Kinsbursky mutex_lock(&sn->pipefs_sb_lock); 1091c21a588fSStanislav Kinsbursky if (sn->pipefs_sb) 1092c21a588fSStanislav Kinsbursky return sn->pipefs_sb; 1093c21a588fSStanislav Kinsbursky mutex_unlock(&sn->pipefs_sb_lock); 1094c21a588fSStanislav Kinsbursky return NULL; 1095c21a588fSStanislav Kinsbursky } 1096c21a588fSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_get_sb_net); 1097c21a588fSStanislav Kinsbursky 1098c21a588fSStanislav Kinsbursky void rpc_put_sb_net(const struct net *net) 1099c21a588fSStanislav Kinsbursky { 1100c21a588fSStanislav Kinsbursky struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1101c21a588fSStanislav Kinsbursky 1102749386e9SWeston Andros Adamson WARN_ON(sn->pipefs_sb == NULL); 1103c21a588fSStanislav Kinsbursky mutex_unlock(&sn->pipefs_sb_lock); 1104c21a588fSStanislav Kinsbursky } 1105c21a588fSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_put_sb_net); 1106c21a588fSStanislav Kinsbursky 11071da177e4SLinus Torvalds static int 11081da177e4SLinus Torvalds rpc_fill_super(struct super_block *sb, void *data, int silent) 11091da177e4SLinus Torvalds { 11101da177e4SLinus Torvalds struct inode *inode; 11111da177e4SLinus Torvalds struct dentry *root; 111238b0da75SStanislav Kinsbursky struct net *net = data; 111390c4e829SStanislav Kinsbursky struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 11142d00131aSStanislav Kinsbursky int err; 11151da177e4SLinus Torvalds 11161da177e4SLinus Torvalds sb->s_blocksize = PAGE_CACHE_SIZE; 11171da177e4SLinus Torvalds sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 11181da177e4SLinus Torvalds sb->s_magic = RPCAUTH_GSSMAGIC; 11191da177e4SLinus Torvalds sb->s_op = &s_ops; 11201da177e4SLinus Torvalds sb->s_time_gran = 1; 11211da177e4SLinus Torvalds 11227e450b4eSJeff Layton inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); 112348fde701SAl Viro sb->s_root = root = d_make_root(inode); 112448fde701SAl Viro if (!root) 11251da177e4SLinus Torvalds return -ENOMEM; 1126ac6feceeSTrond Myklebust if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) 11271da177e4SLinus Torvalds return -ENOMEM; 1128d8af9bc1SChuck Lever dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", 1129d8af9bc1SChuck Lever net, NET_NAME(net)); 113038481605SStanislav Kinsbursky mutex_lock(&sn->pipefs_sb_lock); 113137629b57SStanislav Kinsbursky sn->pipefs_sb = sb; 11322d00131aSStanislav Kinsbursky err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, 11332d00131aSStanislav Kinsbursky RPC_PIPEFS_MOUNT, 11342d00131aSStanislav Kinsbursky sb); 11352d00131aSStanislav Kinsbursky if (err) 11362d00131aSStanislav Kinsbursky goto err_depopulate; 1137021c68deSStanislav Kinsbursky sb->s_fs_info = get_net(net); 113838481605SStanislav Kinsbursky mutex_unlock(&sn->pipefs_sb_lock); 1139fc7bed8cSAl Viro return 0; 11402d00131aSStanislav Kinsbursky 11412d00131aSStanislav Kinsbursky err_depopulate: 11422d00131aSStanislav Kinsbursky blocking_notifier_call_chain(&rpc_pipefs_notifier_list, 11432d00131aSStanislav Kinsbursky RPC_PIPEFS_UMOUNT, 11442d00131aSStanislav Kinsbursky sb); 114537629b57SStanislav Kinsbursky sn->pipefs_sb = NULL; 11462d00131aSStanislav Kinsbursky __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); 114738481605SStanislav Kinsbursky mutex_unlock(&sn->pipefs_sb_lock); 11482d00131aSStanislav Kinsbursky return err; 11491da177e4SLinus Torvalds } 11501da177e4SLinus Torvalds 1151fc14f2feSAl Viro static struct dentry * 1152fc14f2feSAl Viro rpc_mount(struct file_system_type *fs_type, 1153fc14f2feSAl Viro int flags, const char *dev_name, void *data) 11541da177e4SLinus Torvalds { 115538b0da75SStanislav Kinsbursky return mount_ns(fs_type, flags, current->nsproxy->net_ns, rpc_fill_super); 11561da177e4SLinus Torvalds } 11571da177e4SLinus Torvalds 115809acfea5STrond Myklebust static void rpc_kill_sb(struct super_block *sb) 1159021c68deSStanislav Kinsbursky { 1160021c68deSStanislav Kinsbursky struct net *net = sb->s_fs_info; 116190c4e829SStanislav Kinsbursky struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1162021c68deSStanislav Kinsbursky 1163c21a588fSStanislav Kinsbursky mutex_lock(&sn->pipefs_sb_lock); 1164642fe4d0STrond Myklebust if (sn->pipefs_sb != sb) { 1165642fe4d0STrond Myklebust mutex_unlock(&sn->pipefs_sb_lock); 1166642fe4d0STrond Myklebust goto out; 1167642fe4d0STrond Myklebust } 116890c4e829SStanislav Kinsbursky sn->pipefs_sb = NULL; 1169d8af9bc1SChuck Lever dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", 1170d8af9bc1SChuck Lever net, NET_NAME(net)); 11712d00131aSStanislav Kinsbursky blocking_notifier_call_chain(&rpc_pipefs_notifier_list, 11722d00131aSStanislav Kinsbursky RPC_PIPEFS_UMOUNT, 11732d00131aSStanislav Kinsbursky sb); 1174adb6fa7fSStanislav Kinsbursky mutex_unlock(&sn->pipefs_sb_lock); 1175642fe4d0STrond Myklebust put_net(net); 1176642fe4d0STrond Myklebust out: 1177021c68deSStanislav Kinsbursky kill_litter_super(sb); 11781da177e4SLinus Torvalds } 11791da177e4SLinus Torvalds 11801da177e4SLinus Torvalds static struct file_system_type rpc_pipe_fs_type = { 11811da177e4SLinus Torvalds .owner = THIS_MODULE, 11821da177e4SLinus Torvalds .name = "rpc_pipefs", 1183fc14f2feSAl Viro .mount = rpc_mount, 1184021c68deSStanislav Kinsbursky .kill_sb = rpc_kill_sb, 11851da177e4SLinus Torvalds }; 11867f78e035SEric W. Biederman MODULE_ALIAS_FS("rpc_pipefs"); 1187fa7614ddSEric W. Biederman MODULE_ALIAS("rpc_pipefs"); 11881da177e4SLinus Torvalds 11891da177e4SLinus Torvalds static void 119051cc5068SAlexey Dobriyan init_once(void *foo) 11911da177e4SLinus Torvalds { 11921da177e4SLinus Torvalds struct rpc_inode *rpci = (struct rpc_inode *) foo; 11931da177e4SLinus Torvalds 11941da177e4SLinus Torvalds inode_init_once(&rpci->vfs_inode); 11951da177e4SLinus Torvalds rpci->private = NULL; 1196ba9e0975SStanislav Kinsbursky rpci->pipe = NULL; 11971da177e4SLinus Torvalds init_waitqueue_head(&rpci->waitq); 11981da177e4SLinus Torvalds } 11991da177e4SLinus Torvalds 12001da177e4SLinus Torvalds int register_rpc_pipefs(void) 12011da177e4SLinus Torvalds { 12025bd5f581SAkinobu Mita int err; 12035bd5f581SAkinobu Mita 12041da177e4SLinus Torvalds rpc_inode_cachep = kmem_cache_create("rpc_inode_cache", 12051da177e4SLinus Torvalds sizeof(struct rpc_inode), 1206fffb60f9SPaul Jackson 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| 1207fffb60f9SPaul Jackson SLAB_MEM_SPREAD), 120820c2df83SPaul Mundt init_once); 12091da177e4SLinus Torvalds if (!rpc_inode_cachep) 12101da177e4SLinus Torvalds return -ENOMEM; 121180df9d20SStanislav Kinsbursky err = rpc_clients_notifier_register(); 121280df9d20SStanislav Kinsbursky if (err) 121380df9d20SStanislav Kinsbursky goto err_notifier; 12145bd5f581SAkinobu Mita err = register_filesystem(&rpc_pipe_fs_type); 121580df9d20SStanislav Kinsbursky if (err) 121680df9d20SStanislav Kinsbursky goto err_register; 121780df9d20SStanislav Kinsbursky return 0; 121880df9d20SStanislav Kinsbursky 121980df9d20SStanislav Kinsbursky err_register: 122080df9d20SStanislav Kinsbursky rpc_clients_notifier_unregister(); 122180df9d20SStanislav Kinsbursky err_notifier: 12225bd5f581SAkinobu Mita kmem_cache_destroy(rpc_inode_cachep); 12235bd5f581SAkinobu Mita return err; 12245bd5f581SAkinobu Mita } 12255bd5f581SAkinobu Mita 12261da177e4SLinus Torvalds void unregister_rpc_pipefs(void) 12271da177e4SLinus Torvalds { 122880df9d20SStanislav Kinsbursky rpc_clients_notifier_unregister(); 12291a1d92c1SAlexey Dobriyan kmem_cache_destroy(rpc_inode_cachep); 12301da177e4SLinus Torvalds unregister_filesystem(&rpc_pipe_fs_type); 12311da177e4SLinus Torvalds } 1232