+static ssize_t write_ports(struct file *file, char *buf, size_t size)
+{
+ /*
+ * Format:
+ * family proto proto address port
+ */
+ char *mesg = buf;
+ char *family, *udp, *tcp, *addr;
+ int len, port = 0;
+ ssize_t tlen = 0;
+
+ if (buf[size-1] != '\n')
+ return -EINVAL;
+ buf[size-1] = 0;
+
+ family = mesg;
+ len = qword_get(&mesg, family, size);
+ if (len <= 0) return -EINVAL;
+
+ tlen += len;
+ udp = family+len+1;
+ len = qword_get(&mesg, udp, size);
+ if (len <= 0) return -EINVAL;
+
+ tlen += len;
+ tcp = udp+len+1;
+ len = qword_get(&mesg, tcp, size);
+ if (len <= 0) return -EINVAL;
+
+ tlen += len;
+ addr = tcp+len+1;
+ len = qword_get(&mesg, addr, size);
+ if (len <= 0) return -EINVAL;
+
+ len = get_int(&mesg, &port);
+ if (len)
+ return len;
+
+ tlen += sizeof(port);
+ if (port)
+ nfsd_port = port;
+
+ if (strcmp(tcp, "tcp") == 0 || strcmp(tcp, "TCP") == 0)
+ NFSCTL_TCPSET(nfsd_portbits);
+ else
+ NFSCTL_TCPUNSET(nfsd_portbits);
+
+ if (strcmp(udp, "udp") == 0 || strcmp(udp, "UDP") == 0)
+ NFSCTL_UDPSET(nfsd_portbits);
+ else
+ NFSCTL_UDPUNSET(nfsd_portbits);
+
+ return tlen;
+}
+static ssize_t write_versions(struct file *file, char *buf, size_t size)
+{
+ /*
+ * Format:
+ * [-/+]vers [-/+]vers ...
+ */
+ char *mesg = buf;
+ char *vers, sign;
+ int len, num;
+ ssize_t tlen = 0;
+ char *sep;
+
+ if (size>0) {
+ if (nfsd_serv)
+ return -EBUSY;
+ if (buf[size-1] != '\n')
+ return -EINVAL;
+ buf[size-1] = 0;
+
+ vers = mesg;
+ len = qword_get(&mesg, vers, size);
+ if (len <= 0) return -EINVAL;
+ do {
+ sign = *vers;
+ if (sign == '+' || sign == '-')
+ num = simple_strtol((vers+1), NULL, 0);
+ else
+ num = simple_strtol(vers, NULL, 0);
+ switch(num) {
+ case 2:
+ case 3:
+ case 4:
+ if (sign != '-')
+ NFSCTL_VERSET(nfsd_versbits, num);
+ else
+ NFSCTL_VERUNSET(nfsd_versbits, num);
+ break;
+ default:
+ return -EINVAL;
+ }
+ vers += len + 1;
+ tlen += len;
+ } while ((len = qword_get(&mesg, vers, size)) > 0);
+ /* If all get turned off, turn them back on, as
+ * having no versions is BAD
+ */
+ if ((nfsd_versbits & NFSCTL_VERALL)==0)
+ nfsd_versbits = NFSCTL_VERALL;
+ }
+ /* Now write current state into reply buffer */
+ len = 0;
+ sep = "";
+ for (num=2 ; num <= 4 ; num++)
+ if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) {
+ len += sprintf(buf+len, "%s%c%d", sep,
+ NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-',
+ num);
+ sep = " ";
+ }
+ len += sprintf(buf+len, "\n");
+ return len;
+}
+
+#ifdef CONFIG_NFSD_V4
+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);
+}
+
+static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
+{
+ char *mesg = buf;
+ char *recdir;
+ int len, status;
+
+ if (size > PATH_MAX || buf[size-1] != '\n')
+ return -EINVAL;
+ buf[size-1] = 0;
+
+ recdir = mesg;
+ len = qword_get(&mesg, recdir, size);
+ if (len <= 0)
+ return -EINVAL;
+
+ status = nfs4_reset_recoverydir(recdir);
+ return strlen(buf);
+}
+#endif