Skip to content

Commit 3dd98a3

Browse files
jtlaytonJ. Bruce Fields
authored andcommitted
knfsd: clean up nfsd filesystem interfaces
Several of the nfsd filesystem interfaces allow changes to parameters that don't have any effect on a running nfsd service. They are only ever checked when nfsd is started. This patch fixes it so that changes to those procfiles return -EBUSY if nfsd is already running to make it clear that changes on the fly don't work. The patch should also close some relatively harmless races between changing the info in those interfaces and starting nfsd, since these variables are being moved under the protection of the nfsd_mutex. Finally, the nfsv4recoverydir file always returns -EINVAL if read. This patch fixes it to return the recoverydir path as expected. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
1 parent bedbdd8 commit 3dd98a3

File tree

3 files changed

+74
-17
lines changed

3 files changed

+74
-17
lines changed

fs/nfsd/nfs4state.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3249,12 +3249,14 @@ nfs4_state_shutdown(void)
32493249
nfs4_unlock_state();
32503250
}
32513251

3252+
/*
3253+
* user_recovery_dirname is protected by the nfsd_mutex since it's only
3254+
* accessed when nfsd is starting.
3255+
*/
32523256
static void
32533257
nfs4_set_recdir(char *recdir)
32543258
{
3255-
nfs4_lock_state();
32563259
strcpy(user_recovery_dirname, recdir);
3257-
nfs4_unlock_state();
32583260
}
32593261

32603262
/*
@@ -3278,6 +3280,12 @@ nfs4_reset_recoverydir(char *recdir)
32783280
return status;
32793281
}
32803282

3283+
char *
3284+
nfs4_recoverydir(void)
3285+
{
3286+
return user_recovery_dirname;
3287+
}
3288+
32813289
/*
32823290
* Called when leasetime is changed.
32833291
*
@@ -3286,11 +3294,12 @@ nfs4_reset_recoverydir(char *recdir)
32863294
* we start to register any changes in lease time. If the administrator
32873295
* really wants to change the lease time *now*, they can go ahead and bring
32883296
* nfsd down and then back up again after changing the lease time.
3297+
*
3298+
* user_lease_time is protected by nfsd_mutex since it's only really accessed
3299+
* when nfsd is starting
32893300
*/
32903301
void
32913302
nfs4_reset_lease(time_t leasetime)
32923303
{
3293-
lock_kernel();
32943304
user_lease_time = leasetime;
3295-
unlock_kernel();
32963305
}

fs/nfsd/nfsctl.c

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
509509
return rv;
510510
}
511511

512-
static ssize_t write_versions(struct file *file, char *buf, size_t size)
512+
static ssize_t __write_versions(struct file *file, char *buf, size_t size)
513513
{
514514
/*
515515
* Format:
@@ -572,6 +572,16 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
572572
return len;
573573
}
574574

575+
static ssize_t write_versions(struct file *file, char *buf, size_t size)
576+
{
577+
ssize_t rv;
578+
579+
mutex_lock(&nfsd_mutex);
580+
rv = __write_versions(file, buf, size);
581+
mutex_unlock(&nfsd_mutex);
582+
return rv;
583+
}
584+
575585
static ssize_t __write_ports(struct file *file, char *buf, size_t size)
576586
{
577587
if (size == 0) {
@@ -675,6 +685,7 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
675685
static ssize_t write_ports(struct file *file, char *buf, size_t size)
676686
{
677687
ssize_t rv;
688+
678689
mutex_lock(&nfsd_mutex);
679690
rv = __write_ports(file, buf, size);
680691
mutex_unlock(&nfsd_mutex);
@@ -714,16 +725,17 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
714725
#ifdef CONFIG_NFSD_V4
715726
extern time_t nfs4_leasetime(void);
716727

717-
static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
728+
static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
718729
{
719730
/* if size > 10 seconds, call
720731
* nfs4_reset_lease() then write out the new lease (seconds) as reply
721732
*/
722733
char *mesg = buf;
723-
int rv;
734+
int rv, lease;
724735

725736
if (size > 0) {
726-
int lease;
737+
if (nfsd_serv)
738+
return -EBUSY;
727739
rv = get_int(&mesg, &lease);
728740
if (rv)
729741
return rv;
@@ -735,24 +747,52 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
735747
return strlen(buf);
736748
}
737749

738-
static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
750+
static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
751+
{
752+
ssize_t rv;
753+
754+
mutex_lock(&nfsd_mutex);
755+
rv = __write_leasetime(file, buf, size);
756+
mutex_unlock(&nfsd_mutex);
757+
return rv;
758+
}
759+
760+
extern char *nfs4_recoverydir(void);
761+
762+
static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
739763
{
740764
char *mesg = buf;
741765
char *recdir;
742766
int len, status;
743767

744-
if (size == 0 || size > PATH_MAX || buf[size-1] != '\n')
745-
return -EINVAL;
746-
buf[size-1] = 0;
768+
if (size > 0) {
769+
if (nfsd_serv)
770+
return -EBUSY;
771+
if (size > PATH_MAX || buf[size-1] != '\n')
772+
return -EINVAL;
773+
buf[size-1] = 0;
747774

748-
recdir = mesg;
749-
len = qword_get(&mesg, recdir, size);
750-
if (len <= 0)
751-
return -EINVAL;
775+
recdir = mesg;
776+
len = qword_get(&mesg, recdir, size);
777+
if (len <= 0)
778+
return -EINVAL;
752779

753-
status = nfs4_reset_recoverydir(recdir);
780+
status = nfs4_reset_recoverydir(recdir);
781+
}
782+
sprintf(buf, "%s\n", nfs4_recoverydir());
754783
return strlen(buf);
755784
}
785+
786+
static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
787+
{
788+
ssize_t rv;
789+
790+
mutex_lock(&nfsd_mutex);
791+
rv = __write_recoverydir(file, buf, size);
792+
mutex_unlock(&nfsd_mutex);
793+
return rv;
794+
}
795+
756796
#endif
757797

758798
/*----------------------------------------------------------------------------*/

fs/nfsd/nfssvc.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ static DEFINE_SPINLOCK(nfsd_call_lock);
7070
* Transitions of the thread count between zero and non-zero are of particular
7171
* interest since the svc_serv needs to be created and initialized at that
7272
* point, or freed.
73+
*
74+
* Finally, the nfsd_mutex also protects some of the global variables that are
75+
* accessed when nfsd starts and that are settable via the write_* routines in
76+
* nfsctl.c. In particular:
77+
*
78+
* user_recovery_dirname
79+
* user_lease_time
80+
* nfsd_versions
7381
*/
7482
DEFINE_MUTEX(nfsd_mutex);
7583
struct svc_serv *nfsd_serv;

0 commit comments

Comments
 (0)