vserver 1.9.3
[linux-2.6.git] / fs / nfsd / nfsctl.c
index 9c93992..161afdc 100644 (file)
@@ -80,101 +80,31 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
        [NFSD_Leasetime] = write_leasetime,
 };
 
-/* an argresp is stored in an allocated page and holds the 
- * size of the argument or response, along with its content
- */
-struct argresp {
-       ssize_t size;
-       char data[0];
-};
-
-/*
- * transaction based IO methods.
- * The file expects a single write which triggers the transaction, and then
- * possibly a read which collects the result - which is stored in a 
- * file-local buffer.
- */
-static ssize_t TA_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
 {
        ino_t ino =  file->f_dentry->d_inode->i_ino;
-       struct argresp *ar;
-       ssize_t rv = 0;
+       char *data;
+       ssize_t rv;
 
        if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
                return -EINVAL;
-       if (file->private_data) 
-               return -EINVAL; /* only one write allowed per open */
-       if (size > PAGE_SIZE - sizeof(struct argresp))
-               return -EFBIG;
 
-       ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!ar)
-               return -ENOMEM;
-       ar->size = 0;
-       down(&file->f_dentry->d_inode->i_sem);
-       if (file->private_data)
-               rv = -EINVAL;
-       else
-               file->private_data = ar;
-       up(&file->f_dentry->d_inode->i_sem);
-       if (rv) {
-               kfree(ar);
-               return rv;
-       }
-       if (copy_from_user(ar->data, buf, size))
-               return -EFAULT;
-       
-       rv =  write_op[ino](file, ar->data, size);
+       data = simple_transaction_get(file, buf, size);
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       rv =  write_op[ino](file, data, size);
        if (rv>0) {
-               ar->size = rv;
+               simple_transaction_set(file, rv);
                rv = size;
        }
        return rv;
 }
 
-
-static ssize_t TA_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
-{
-       struct argresp *ar;
-       ssize_t rv = 0;
-       
-       if (file->private_data == NULL)
-               rv = TA_write(file, buf, 0, pos);
-       if (rv < 0)
-               return rv;
-
-       ar = file->private_data;
-       if (!ar)
-               return 0;
-       if (*pos >= ar->size)
-               return 0;
-       if (*pos + size > ar->size)
-               size = ar->size - *pos;
-       if (copy_to_user(buf, ar->data + *pos, size))
-               return -EFAULT;
-       *pos += size;
-       return size;
-}
-
-static int TA_open(struct inode *inode, struct file *file)
-{
-       file->private_data = NULL;
-       return 0;
-}
-
-static int TA_release(struct inode *inode, struct file *file)
-{
-       void *p = file->private_data;
-       file->private_data = NULL;
-       kfree(p);
-       return 0;
-}
-
 static struct file_operations transaction_ops = {
-       .write          = TA_write,
-       .read           = TA_read,
-       .open           = TA_open,
-       .release        = TA_release,
+       .write          = nfsctl_transaction_write,
+       .read           = simple_transaction_read,
+       .release        = simple_transaction_release,
 };
 
 extern struct seq_operations nfs_exports_op;
@@ -366,7 +296,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
        if (len)
                return len;
        
-       mesg = buf; len = PAGE_SIZE-sizeof(struct argresp);
+       mesg = buf; len = SIMPLE_TRANSACTION_LIMIT;
        qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
        mesg[-1] = '\n';
        return mesg - buf;