X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fnfsd%2Fnfsctl.c;h=161afdcb8f7d911b81035e3a76f20a5aad05635e;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=5014476b1d8717f8ee42305060917f719525dfaa;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 5014476b1..161afdcb8 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -36,7 +36,7 @@ #include /* - * We have a single directory with 8 nodes in it. + * We have a single directory with 9 nodes in it. */ enum { NFSD_Root = 1, @@ -50,6 +50,7 @@ enum { NFSD_List, NFSD_Fh, NFSD_Threads, + NFSD_Leasetime, }; /* @@ -64,6 +65,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size); static ssize_t write_getfs(struct file *file, char *buf, size_t size); static ssize_t write_filehandle(struct file *file, char *buf, size_t size); static ssize_t write_threads(struct file *file, char *buf, size_t size); +static ssize_t write_leasetime(struct file *file, char *buf, size_t size); static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Svc] = write_svc, @@ -75,103 +77,34 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Getfs] = write_getfs, [NFSD_Fh] = write_filehandle, [NFSD_Threads] = write_threads, + [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; @@ -363,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; @@ -393,6 +326,29 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) return strlen(buf); } +extern time_t nfs4_leasetime(void); + +static ssize_t write_leasetime(struct file *file, char *buf, size_t size) +{ + /* if size > 10 seconds, call + * nfs4_reset_lease() then write out the new lease (seconds) as reply + */ + char *mesg = buf; + int rv; + + if (size > 0) { + int lease; + rv = get_int(&mesg, &lease); + if (rv) + return rv; + if (lease < 10 || lease > 3600) + return -EINVAL; + nfs4_reset_lease(lease); + } + sprintf(buf, "%ld\n", nfs4_lease_time()); + return strlen(buf); +} + /*----------------------------------------------------------------------------*/ /* * populating the filesystem. @@ -411,6 +367,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, +#ifdef CONFIG_NFSD_V4 + [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, +#endif /* last one */ {""} }; return simple_fill_super(sb, 0x6e667364, nfsd_files); @@ -441,7 +400,7 @@ static int __init init_nfsd(void) #ifdef CONFIG_NFSD_V4 nfsd_idmap_init(); /* Name to ID mapping */ #endif /* CONFIG_NFSD_V4 */ - if (proc_mkdir("fs/nfs", 0)) { + if (proc_mkdir("fs/nfs", NULL)) { struct proc_dir_entry *entry; entry = create_proc_entry("fs/nfs/exports", 0, NULL); if (entry)