X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fnfsd%2Fnfsctl.c;h=161afdcb8f7d911b81035e3a76f20a5aad05635e;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=9c9399258afd06bf7ef26ac036a1c1014793dbe5;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 9c9399258..161afdcb8 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -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;