*
* Userland/kernel interface for rpcauth_gss.
* Code shamelessly plagiarized from fs/nfsd/nfsctl.c
- * and fs/driverfs/inode.c
+ * and fs/sysfs/inode.c
*
* Copyright (c) 2002, Trond Myklebust <trond.myklebust@fys.uio.no>
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
-static struct vfsmount *rpc_mount;
+static struct vfsmount *rpc_mount __read_mostly;
static int rpc_mount_count;
static struct file_system_type rpc_pipe_fs_type;
-static kmem_cache_t *rpc_inode_cachep;
+static struct kmem_cache *rpc_inode_cachep __read_mostly;
#define RPC_UPCALL_TIMEOUT (30*HZ)
-static void
-__rpc_purge_upcall(struct inode *inode, int err)
+static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head,
+ void (*destroy_msg)(struct rpc_pipe_msg *), int err)
{
- struct rpc_inode *rpci = RPC_I(inode);
struct rpc_pipe_msg *msg;
- while (!list_empty(&rpci->pipe)) {
- msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, list);
- list_del_init(&msg->list);
- msg->errno = err;
- rpci->ops->destroy_msg(msg);
- }
- while (!list_empty(&rpci->in_upcall)) {
- msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, list);
- list_del_init(&msg->list);
+ if (list_empty(head))
+ return;
+ do {
+ msg = list_entry(head->next, struct rpc_pipe_msg, list);
+ list_del(&msg->list);
msg->errno = err;
- rpci->ops->destroy_msg(msg);
- }
- rpci->pipelen = 0;
+ destroy_msg(msg);
+ } while (!list_empty(head));
wake_up(&rpci->waitq);
}
static void
-rpc_timeout_upcall_queue(void *data)
+rpc_timeout_upcall_queue(struct work_struct *work)
{
- struct rpc_inode *rpci = (struct rpc_inode *)data;
+ LIST_HEAD(free_list);
+ struct rpc_inode *rpci =
+ container_of(work, struct rpc_inode, queue_timeout.work);
struct inode *inode = &rpci->vfs_inode;
+ void (*destroy_msg)(struct rpc_pipe_msg *);
- down(&inode->i_sem);
- if (rpci->nreaders == 0 && !list_empty(&rpci->pipe))
- __rpc_purge_upcall(inode, -ETIMEDOUT);
- up(&inode->i_sem);
+ spin_lock(&inode->i_lock);
+ if (rpci->ops == NULL) {
+ spin_unlock(&inode->i_lock);
+ return;
+ }
+ destroy_msg = rpci->ops->destroy_msg;
+ if (rpci->nreaders == 0) {
+ list_splice_init(&rpci->pipe, &free_list);
+ rpci->pipelen = 0;
+ }
+ spin_unlock(&inode->i_lock);
+ rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT);
}
int
rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
{
struct rpc_inode *rpci = RPC_I(inode);
- int res = 0;
+ int res = -EPIPE;
- down(&inode->i_sem);
+ spin_lock(&inode->i_lock);
+ if (rpci->ops == NULL)
+ goto out;
if (rpci->nreaders) {
list_add_tail(&msg->list, &rpci->pipe);
rpci->pipelen += msg->len;
+ res = 0;
} else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) {
if (list_empty(&rpci->pipe))
- schedule_delayed_work(&rpci->queue_timeout,
+ queue_delayed_work(rpciod_workqueue,
+ &rpci->queue_timeout,
RPC_UPCALL_TIMEOUT);
list_add_tail(&msg->list, &rpci->pipe);
rpci->pipelen += msg->len;
- } else
- res = -EPIPE;
- up(&inode->i_sem);
+ res = 0;
+ }
+out:
+ spin_unlock(&inode->i_lock);
wake_up(&rpci->waitq);
return res;
}
+static inline void
+rpc_inode_setowner(struct inode *inode, void *private)
+{
+ RPC_I(inode)->private = private;
+}
+
static void
rpc_close_pipes(struct inode *inode)
{
struct rpc_inode *rpci = RPC_I(inode);
+ struct rpc_pipe_ops *ops;
- cancel_delayed_work(&rpci->queue_timeout);
- flush_scheduled_work();
- down(&inode->i_sem);
- if (rpci->ops != NULL) {
+ mutex_lock(&inode->i_mutex);
+ ops = rpci->ops;
+ if (ops != NULL) {
+ LIST_HEAD(free_list);
+
+ spin_lock(&inode->i_lock);
rpci->nreaders = 0;
- __rpc_purge_upcall(inode, -EPIPE);
- rpci->nwriters = 0;
- if (rpci->ops->release_pipe)
- rpci->ops->release_pipe(inode);
+ list_splice_init(&rpci->in_upcall, &free_list);
+ list_splice_init(&rpci->pipe, &free_list);
+ rpci->pipelen = 0;
rpci->ops = NULL;
+ spin_unlock(&inode->i_lock);
+ rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE);
+ rpci->nwriters = 0;
+ if (ops->release_pipe)
+ ops->release_pipe(inode);
+ cancel_delayed_work(&rpci->queue_timeout);
+ flush_workqueue(rpciod_workqueue);
}
- up(&inode->i_sem);
-}
-
-static inline void
-rpc_inode_setowner(struct inode *inode, void *private)
-{
- RPC_I(inode)->private = private;
+ rpc_inode_setowner(inode, NULL);
+ mutex_unlock(&inode->i_mutex);
}
static struct inode *
rpc_alloc_inode(struct super_block *sb)
{
struct rpc_inode *rpci;
- rpci = (struct rpc_inode *)kmem_cache_alloc(rpc_inode_cachep, SLAB_KERNEL);
+ rpci = (struct rpc_inode *)kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL);
if (!rpci)
return NULL;
return &rpci->vfs_inode;
struct rpc_inode *rpci = RPC_I(inode);
int res = -ENXIO;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (rpci->ops != NULL) {
if (filp->f_mode & FMODE_READ)
rpci->nreaders ++;
rpci->nwriters ++;
res = 0;
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return res;
}
static int
rpc_pipe_release(struct inode *inode, struct file *filp)
{
- struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+ struct rpc_inode *rpci = RPC_I(inode);
struct rpc_pipe_msg *msg;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (rpci->ops == NULL)
goto out;
msg = (struct rpc_pipe_msg *)filp->private_data;
if (msg != NULL) {
- msg->errno = -EPIPE;
- list_del_init(&msg->list);
+ spin_lock(&inode->i_lock);
+ msg->errno = -EAGAIN;
+ list_del(&msg->list);
+ spin_unlock(&inode->i_lock);
rpci->ops->destroy_msg(msg);
}
if (filp->f_mode & FMODE_WRITE)
rpci->nwriters --;
- if (filp->f_mode & FMODE_READ)
+ if (filp->f_mode & FMODE_READ) {
rpci->nreaders --;
- if (!rpci->nreaders)
- __rpc_purge_upcall(inode, -EPIPE);
+ if (rpci->nreaders == 0) {
+ LIST_HEAD(free_list);
+ spin_lock(&inode->i_lock);
+ list_splice_init(&rpci->pipe, &free_list);
+ rpci->pipelen = 0;
+ spin_unlock(&inode->i_lock);
+ rpc_purge_list(rpci, &free_list,
+ rpci->ops->destroy_msg, -EAGAIN);
+ }
+ }
if (rpci->ops->release_pipe)
rpci->ops->release_pipe(inode);
out:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return 0;
}
static ssize_t
rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct rpc_inode *rpci = RPC_I(inode);
struct rpc_pipe_msg *msg;
int res = 0;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (rpci->ops == NULL) {
res = -EPIPE;
goto out_unlock;
}
msg = filp->private_data;
if (msg == NULL) {
+ spin_lock(&inode->i_lock);
if (!list_empty(&rpci->pipe)) {
msg = list_entry(rpci->pipe.next,
struct rpc_pipe_msg,
filp->private_data = msg;
msg->copied = 0;
}
+ spin_unlock(&inode->i_lock);
if (msg == NULL)
goto out_unlock;
}
res = rpci->ops->upcall(filp, msg, buf, len);
if (res < 0 || msg->len == msg->copied) {
filp->private_data = NULL;
- list_del_init(&msg->list);
+ spin_lock(&inode->i_lock);
+ list_del(&msg->list);
+ spin_unlock(&inode->i_lock);
rpci->ops->destroy_msg(msg);
}
out_unlock:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return res;
}
static ssize_t
rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct rpc_inode *rpci = RPC_I(inode);
int res;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
res = -EPIPE;
if (rpci->ops != NULL)
res = rpci->ops->downcall(filp, buf, len);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return res;
}
struct rpc_inode *rpci;
unsigned int mask = 0;
- rpci = RPC_I(filp->f_dentry->d_inode);
+ rpci = RPC_I(filp->f_path.dentry->d_inode);
poll_wait(filp, &rpci->waitq, wait);
mask = POLLOUT | POLLWRNORM;
rpc_pipe_ioctl(struct inode *ino, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+ struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
int len;
switch (cmd) {
}
}
-struct inode_operations rpc_pipe_iops = {
- .lookup = simple_lookup,
-};
-
-
-struct file_operations rpc_pipe_fops = {
+static struct file_operations rpc_pipe_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = rpc_pipe_read,
seq_printf(m, "RPC server: %s\n", clnt->cl_server);
seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname,
clnt->cl_prog, clnt->cl_vers);
- seq_printf(m, "address: %u.%u.%u.%u\n",
- NIPQUAD(clnt->cl_xprt->addr.sin_addr.s_addr));
- seq_printf(m, "protocol: %s\n",
- clnt->cl_xprt->prot == IPPROTO_UDP ? "udp" : "tcp");
+ seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
+ seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO));
return 0;
}
if (!ret) {
struct seq_file *m = file->private_data;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
clnt = RPC_I(inode)->private;
if (clnt) {
atomic_inc(&clnt->cl_users);
single_release(inode, file);
ret = -EINVAL;
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
return ret;
}
*/
struct rpc_filelist {
char *name;
- struct file_operations *i_fop;
+ const struct file_operations *i_fop;
int mode;
};
},
};
-static int
-rpc_get_mount(void)
+struct vfsmount *rpc_get_mount(void)
{
- return simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
+ int err;
+
+ err = simple_pin_fs(&rpc_pipe_fs_type, &rpc_mount, &rpc_mount_count);
+ if (err != 0)
+ return ERR_PTR(err);
+ return rpc_mount;
}
-static void
-rpc_put_mount(void)
+void rpc_put_mount(void)
{
simple_release_fs(&rpc_mount, &rpc_mount_count);
}
{
if (path[0] == '\0')
return -ENOENT;
- if (rpc_get_mount()) {
+ nd->mnt = rpc_get_mount();
+ if (IS_ERR(nd->mnt)) {
printk(KERN_WARNING "%s: %s failed to mount "
"pseudofilesystem \n", __FILE__, __FUNCTION__);
- return -ENODEV;
+ return PTR_ERR(nd->mnt);
}
- nd->mnt = mntget(rpc_mount);
+ mntget(nd->mnt);
nd->dentry = dget(rpc_mount->mnt_root);
nd->last_type = LAST_ROOT;
nd->flags = LOOKUP_PARENT;
return NULL;
inode->i_mode = mode;
inode->i_uid = inode->i_gid = 0;
- inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
switch(mode & S_IFMT) {
case S_IFDIR:
inode->i_fop = &simple_dir_operations;
inode->i_op = &simple_dir_inode_operations;
- inode->i_nlink++;
+ inc_nlink(inode);
default:
break;
}
struct dentry *dentry, *dvec[10];
int n = 0;
- down(&dir->i_sem);
+ mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD);
repeat:
spin_lock(&dcache_lock);
list_for_each_safe(pos, next, &parent->d_subdirs) {
- dentry = list_entry(pos, struct dentry, d_child);
+ dentry = list_entry(pos, struct dentry, d_u.d_child);
spin_lock(&dentry->d_lock);
if (!d_unhashed(dentry)) {
dget_locked(dentry);
dentry = dvec[--n];
if (dentry->d_inode) {
rpc_close_pipes(dentry->d_inode);
- rpc_inode_setowner(dentry->d_inode, NULL);
simple_unlink(dir, dentry);
}
+ inode_dir_notify(dir, DN_DELETE);
dput(dentry);
} while (n);
goto repeat;
}
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
}
static int
{
struct inode *inode, *dir = parent->d_inode;
void *private = RPC_I(dir)->private;
- struct qstr name;
struct dentry *dentry;
int mode, i;
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
for (i = start; i < eof; i++) {
- name.name = files[i].name;
- name.len = strlen(name.name);
- name.hash = full_name_hash(name.name, name.len);
- dentry = d_alloc(parent, &name);
+ dentry = d_alloc_name(parent, files[i].name);
if (!dentry)
goto out_bad;
mode = files[i].mode;
if (private)
rpc_inode_setowner(inode, private);
if (S_ISDIR(mode))
- dir->i_nlink++;
+ inc_nlink(dir);
d_add(dentry, inode);
}
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
return 0;
out_bad:
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
printk(KERN_WARNING "%s: %s failed to populate directory %s\n",
__FILE__, __FUNCTION__, parent->d_name.name);
return -ENOMEM;
goto out_err;
inode->i_ino = iunique(dir->i_sb, 100);
d_instantiate(dentry, inode);
- dir->i_nlink++;
+ inc_nlink(dir);
inode_dir_notify(dir, DN_CREATE);
- rpc_get_mount();
return 0;
out_err:
printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
int error;
shrink_dcache_parent(dentry);
- if (dentry->d_inode) {
- rpc_close_pipes(dentry->d_inode);
- rpc_inode_setowner(dentry->d_inode, NULL);
- }
+ if (d_unhashed(dentry))
+ return 0;
if ((error = simple_rmdir(dir, dentry)) != 0)
return error;
if (!error) {
inode_dir_notify(dir, DN_DELETE);
d_drop(dentry);
- rpc_put_mount();
}
return 0;
}
-struct dentry *
-rpc_lookup_negative(char *path, struct nameidata *nd)
+static struct dentry *
+rpc_lookup_create(struct dentry *parent, const char *name, int len)
{
+ struct inode *dir = parent->d_inode;
struct dentry *dentry;
- struct inode *dir;
- int error;
- if ((error = rpc_lookup_parent(path, nd)) != 0)
- return ERR_PTR(error);
- dir = nd->dentry->d_inode;
- down(&dir->i_sem);
- dentry = lookup_hash(&nd->last, nd->dentry);
+ mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
+ dentry = lookup_one_len(name, parent, len);
if (IS_ERR(dentry))
goto out_err;
if (dentry->d_inode) {
}
return dentry;
out_err:
- up(&dir->i_sem);
- rpc_release_path(nd);
+ mutex_unlock(&dir->i_mutex);
+ return dentry;
+}
+
+static struct dentry *
+rpc_lookup_negative(char *path, struct nameidata *nd)
+{
+ struct dentry *dentry;
+ int error;
+
+ if ((error = rpc_lookup_parent(path, nd)) != 0)
+ return ERR_PTR(error);
+ dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len);
+ if (IS_ERR(dentry))
+ rpc_release_path(nd);
return dentry;
}
RPCAUTH_info, RPCAUTH_EOF);
if (error)
goto err_depopulate;
+ dget(dentry);
out:
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
rpc_release_path(&nd);
return dentry;
err_depopulate:
}
int
-rpc_rmdir(char *path)
+rpc_rmdir(struct dentry *dentry)
{
- struct nameidata nd;
- struct dentry *dentry;
+ struct dentry *parent;
struct inode *dir;
int error;
- if ((error = rpc_lookup_parent(path, &nd)) != 0)
- return error;
- dir = nd.dentry->d_inode;
- down(&dir->i_sem);
- dentry = lookup_hash(&nd.last, nd.dentry);
- if (IS_ERR(dentry)) {
- error = PTR_ERR(dentry);
- goto out_release;
- }
+ parent = dget_parent(dentry);
+ dir = parent->d_inode;
+ mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
rpc_depopulate(dentry);
error = __rpc_rmdir(dir, dentry);
dput(dentry);
-out_release:
- up(&dir->i_sem);
- rpc_release_path(&nd);
+ mutex_unlock(&dir->i_mutex);
+ dput(parent);
return error;
}
struct dentry *
-rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
+rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pipe_ops *ops, int flags)
{
- struct nameidata nd;
struct dentry *dentry;
struct inode *dir, *inode;
struct rpc_inode *rpci;
- dentry = rpc_lookup_negative(path, &nd);
+ dentry = rpc_lookup_create(parent, name, strlen(name));
if (IS_ERR(dentry))
return dentry;
- dir = nd.dentry->d_inode;
- inode = rpc_get_inode(dir->i_sb, S_IFSOCK | S_IRUSR | S_IWUSR);
+ dir = parent->d_inode;
+ inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR);
if (!inode)
goto err_dput;
inode->i_ino = iunique(dir->i_sb, 100);
rpci->flags = flags;
rpci->ops = ops;
inode_dir_notify(dir, DN_CREATE);
+ dget(dentry);
out:
- up(&dir->i_sem);
- rpc_release_path(&nd);
+ mutex_unlock(&dir->i_mutex);
return dentry;
err_dput:
dput(dentry);
dentry = ERR_PTR(-ENOMEM);
- printk(KERN_WARNING "%s: %s() failed to create pipe %s (errno = %d)\n",
- __FILE__, __FUNCTION__, path, -ENOMEM);
+ printk(KERN_WARNING "%s: %s() failed to create pipe %s/%s (errno = %d)\n",
+ __FILE__, __FUNCTION__, parent->d_name.name, name,
+ -ENOMEM);
goto out;
}
int
-rpc_unlink(char *path)
+rpc_unlink(struct dentry *dentry)
{
- struct nameidata nd;
- struct dentry *dentry;
+ struct dentry *parent;
struct inode *dir;
- int error;
+ int error = 0;
- if ((error = rpc_lookup_parent(path, &nd)) != 0)
- return error;
- dir = nd.dentry->d_inode;
- down(&dir->i_sem);
- dentry = lookup_hash(&nd.last, nd.dentry);
- if (IS_ERR(dentry)) {
- error = PTR_ERR(dentry);
- goto out_release;
- }
- d_drop(dentry);
- if (dentry->d_inode) {
- rpc_close_pipes(dentry->d_inode);
- rpc_inode_setowner(dentry->d_inode, NULL);
- error = simple_unlink(dir, dentry);
+ parent = dget_parent(dentry);
+ dir = parent->d_inode;
+ mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
+ if (!d_unhashed(dentry)) {
+ d_drop(dentry);
+ if (dentry->d_inode) {
+ rpc_close_pipes(dentry->d_inode);
+ error = simple_unlink(dir, dentry);
+ }
+ inode_dir_notify(dir, DN_DELETE);
}
dput(dentry);
- inode_dir_notify(dir, DN_DELETE);
-out_release:
- up(&dir->i_sem);
- rpc_release_path(&nd);
+ mutex_unlock(&dir->i_mutex);
+ dput(parent);
return error;
}
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = RPCAUTH_GSSMAGIC;
sb->s_op = &s_ops;
+ sb->s_time_gran = 1;
inode = rpc_get_inode(sb, S_IFDIR | 0755);
if (!inode)
return -ENOMEM;
}
-static struct super_block *
+static int
rpc_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
- return get_sb_single(fs_type, flags, data, rpc_fill_super);
+ return get_sb_single(fs_type, flags, data, rpc_fill_super, mnt);
}
static struct file_system_type rpc_pipe_fs_type = {
};
static void
-init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
{
struct rpc_inode *rpci = (struct rpc_inode *) foo;
INIT_LIST_HEAD(&rpci->pipe);
rpci->pipelen = 0;
init_waitqueue_head(&rpci->waitq);
- INIT_WORK(&rpci->queue_timeout, rpc_timeout_upcall_queue, rpci);
+ INIT_DELAYED_WORK(&rpci->queue_timeout,
+ rpc_timeout_upcall_queue);
rpci->ops = NULL;
}
}
int register_rpc_pipefs(void)
{
rpc_inode_cachep = kmem_cache_create("rpc_inode_cache",
- sizeof(struct rpc_inode),
- 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
- init_once, NULL);
+ sizeof(struct rpc_inode),
+ 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
+ SLAB_MEM_SPREAD),
+ init_once, NULL);
if (!rpc_inode_cachep)
return -ENOMEM;
register_filesystem(&rpc_pipe_fs_type);
void unregister_rpc_pipefs(void)
{
- if (kmem_cache_destroy(rpc_inode_cachep))
- printk(KERN_WARNING "RPC: unable to free inode cache\n");
+ kmem_cache_destroy(rpc_inode_cachep);
unregister_filesystem(&rpc_pipe_fs_type);
}