static void nfsd_adjust_nfsd_versions4(void) { unsigned i; for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) { if (nfsd_supported_minorversions[i]) return; } nfsd_vers(4, NFSD_CLEAR); }
int nfsd_minorversion(u32 minorversion, enum vers_op change) { if (minorversion > NFSD_SUPPORTED_MINOR_VERSION && change != NFSD_AVAIL) return -1; switch(change) { case NFSD_SET: nfsd_supported_minorversions[minorversion] = true; nfsd_vers(4, NFSD_SET); break; case NFSD_CLEAR: nfsd_supported_minorversions[minorversion] = false; nfsd_adjust_nfsd_versions4(); break; case NFSD_TEST: return nfsd_supported_minorversions[minorversion]; case NFSD_AVAIL: return minorversion <= NFSD_SUPPORTED_MINOR_VERSION; } return 0; }
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) /* Cannot change versions without updating * nfsd_serv->sv_xdrsize, and reallocing * rq_argp and rq_resp */ 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: nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET); 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 */ nfsd_reset_versions(); } /* Now write current state into reply buffer */ len = 0; sep = ""; for (num=2 ; num <= 4 ; num++) if (nfsd_vers(num, NFSD_AVAIL)) { len += sprintf(buf+len, "%s%c%d", sep, nfsd_vers(num, NFSD_TEST)?'+':'-', num); sep = " "; } len += sprintf(buf+len, "\n"); return len; }
static ssize_t __write_versions(struct file *file, char *buf, size_t size) { char *mesg = buf; char *vers, *minorp, sign; int len, num, remaining; unsigned minor; ssize_t tlen = 0; char *sep; if (size>0) { if (nfsd_serv) /* Cannot change versions without updating * nfsd_serv->sv_xdrsize, and reallocing * rq_argp and rq_resp */ 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), &minorp, 0); else num = simple_strtol(vers, &minorp, 0); if (*minorp == '.') { if (num < 4) return -EINVAL; minor = simple_strtoul(minorp+1, NULL, 0); if (minor == 0) return -EINVAL; if (nfsd_minorversion(minor, sign == '-' ? NFSD_CLEAR : NFSD_SET) < 0) return -EINVAL; goto next; } switch(num) { case 2: case 3: case 4: nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET); break; default: return -EINVAL; } next: vers += len + 1; } while ((len = qword_get(&mesg, vers, size)) > 0); /* If all get turned off, turn them back on, as * having no versions is BAD */ nfsd_reset_versions(); } /* Now write current state into reply buffer */ len = 0; sep = ""; remaining = SIMPLE_TRANSACTION_LIMIT; for (num=2 ; num <= 4 ; num++) if (nfsd_vers(num, NFSD_AVAIL)) { len = snprintf(buf, remaining, "%s%c%d", sep, nfsd_vers(num, NFSD_TEST)?'+':'-', num); sep = " "; if (len > remaining) break; remaining -= len; buf += len; tlen += len; } if (nfsd_vers(4, NFSD_AVAIL)) for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION; minor++) { len = snprintf(buf, remaining, " %c4.%u", (nfsd_vers(4, NFSD_TEST) && nfsd_minorversion(minor, NFSD_TEST)) ? '+' : '-', minor); if (len > remaining) break; remaining -= len; buf += len; tlen += len; } len = snprintf(buf, remaining, "\n"); if (len > remaining) return -EINVAL; return tlen + len; }