Skip to content

Commit 21179d8

Browse files
jtlaytonJ. Bruce Fields
authored andcommitted
knfsd: don't allocate file_locks on the stack
struct file_lock is pretty large and really ought not live on the stack. On my x86_64 machine, they're almost 200 bytes each. (gdb) p sizeof(struct file_lock) $1 = 192 ...allocate them dynamically instead. Reported-by: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
1 parent 5592a3f commit 21179d8

File tree

1 file changed

+76
-42
lines changed

1 file changed

+76
-42
lines changed

fs/nfsd/nfs4state.c

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4046,8 +4046,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
40464046
struct nfs4_lockowner *lock_sop = NULL;
40474047
struct nfs4_ol_stateid *lock_stp;
40484048
struct file *filp = NULL;
4049-
struct file_lock file_lock;
4050-
struct file_lock conflock;
4049+
struct file_lock *file_lock = NULL;
4050+
struct file_lock *conflock = NULL;
40514051
__be32 status = 0;
40524052
bool new_state = false;
40534053
int lkflg;
@@ -4117,21 +4117,28 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
41174117
if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
41184118
goto out;
41194119

4120-
locks_init_lock(&file_lock);
4120+
file_lock = locks_alloc_lock();
4121+
if (!file_lock) {
4122+
dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4123+
status = nfserr_jukebox;
4124+
goto out;
4125+
}
4126+
4127+
locks_init_lock(file_lock);
41214128
switch (lock->lk_type) {
41224129
case NFS4_READ_LT:
41234130
case NFS4_READW_LT:
41244131
filp = find_readable_file(lock_stp->st_file);
41254132
if (filp)
41264133
get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
4127-
file_lock.fl_type = F_RDLCK;
4134+
file_lock->fl_type = F_RDLCK;
41284135
break;
41294136
case NFS4_WRITE_LT:
41304137
case NFS4_WRITEW_LT:
41314138
filp = find_writeable_file(lock_stp->st_file);
41324139
if (filp)
41334140
get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
4134-
file_lock.fl_type = F_WRLCK;
4141+
file_lock->fl_type = F_WRLCK;
41354142
break;
41364143
default:
41374144
status = nfserr_inval;
@@ -4141,17 +4148,23 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
41414148
status = nfserr_openmode;
41424149
goto out;
41434150
}
4144-
file_lock.fl_owner = (fl_owner_t)lock_sop;
4145-
file_lock.fl_pid = current->tgid;
4146-
file_lock.fl_file = filp;
4147-
file_lock.fl_flags = FL_POSIX;
4148-
file_lock.fl_lmops = &nfsd_posix_mng_ops;
4149-
4150-
file_lock.fl_start = lock->lk_offset;
4151-
file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
4152-
nfs4_transform_lock_offset(&file_lock);
4151+
file_lock->fl_owner = (fl_owner_t)lock_sop;
4152+
file_lock->fl_pid = current->tgid;
4153+
file_lock->fl_file = filp;
4154+
file_lock->fl_flags = FL_POSIX;
4155+
file_lock->fl_lmops = &nfsd_posix_mng_ops;
4156+
file_lock->fl_start = lock->lk_offset;
4157+
file_lock->fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
4158+
nfs4_transform_lock_offset(file_lock);
4159+
4160+
conflock = locks_alloc_lock();
4161+
if (!conflock) {
4162+
dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4163+
status = nfserr_jukebox;
4164+
goto out;
4165+
}
41534166

4154-
err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock);
4167+
err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
41554168
switch (-err) {
41564169
case 0: /* success! */
41574170
update_stateid(&lock_stp->st_stid.sc_stateid);
@@ -4162,7 +4175,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
41624175
case (EAGAIN): /* conflock holds conflicting lock */
41634176
status = nfserr_denied;
41644177
dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
4165-
nfs4_set_lock_denied(&conflock, &lock->lk_denied);
4178+
nfs4_set_lock_denied(conflock, &lock->lk_denied);
41664179
break;
41674180
case (EDEADLK):
41684181
status = nfserr_deadlock;
@@ -4177,6 +4190,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
41774190
release_lockowner(lock_sop);
41784191
if (!cstate->replay_owner)
41794192
nfs4_unlock_state();
4193+
if (file_lock)
4194+
locks_free_lock(file_lock);
4195+
if (conflock)
4196+
locks_free_lock(conflock);
41804197
return status;
41814198
}
41824199

@@ -4205,7 +4222,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
42054222
struct nfsd4_lockt *lockt)
42064223
{
42074224
struct inode *inode;
4208-
struct file_lock file_lock;
4225+
struct file_lock *file_lock = NULL;
42094226
struct nfs4_lockowner *lo;
42104227
__be32 status;
42114228
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
@@ -4226,15 +4243,21 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
42264243
goto out;
42274244

42284245
inode = cstate->current_fh.fh_dentry->d_inode;
4229-
locks_init_lock(&file_lock);
4246+
file_lock = locks_alloc_lock();
4247+
if (!file_lock) {
4248+
dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4249+
status = nfserr_jukebox;
4250+
goto out;
4251+
}
4252+
locks_init_lock(file_lock);
42304253
switch (lockt->lt_type) {
42314254
case NFS4_READ_LT:
42324255
case NFS4_READW_LT:
4233-
file_lock.fl_type = F_RDLCK;
4256+
file_lock->fl_type = F_RDLCK;
42344257
break;
42354258
case NFS4_WRITE_LT:
42364259
case NFS4_WRITEW_LT:
4237-
file_lock.fl_type = F_WRLCK;
4260+
file_lock->fl_type = F_WRLCK;
42384261
break;
42394262
default:
42404263
dprintk("NFSD: nfs4_lockt: bad lock type!\n");
@@ -4244,25 +4267,27 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
42444267

42454268
lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner);
42464269
if (lo)
4247-
file_lock.fl_owner = (fl_owner_t)lo;
4248-
file_lock.fl_pid = current->tgid;
4249-
file_lock.fl_flags = FL_POSIX;
4270+
file_lock->fl_owner = (fl_owner_t)lo;
4271+
file_lock->fl_pid = current->tgid;
4272+
file_lock->fl_flags = FL_POSIX;
42504273

4251-
file_lock.fl_start = lockt->lt_offset;
4252-
file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
4274+
file_lock->fl_start = lockt->lt_offset;
4275+
file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
42534276

4254-
nfs4_transform_lock_offset(&file_lock);
4277+
nfs4_transform_lock_offset(file_lock);
42554278

4256-
status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
4279+
status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock);
42574280
if (status)
42584281
goto out;
42594282

4260-
if (file_lock.fl_type != F_UNLCK) {
4283+
if (file_lock->fl_type != F_UNLCK) {
42614284
status = nfserr_denied;
4262-
nfs4_set_lock_denied(&file_lock, &lockt->lt_denied);
4285+
nfs4_set_lock_denied(file_lock, &lockt->lt_denied);
42634286
}
42644287
out:
42654288
nfs4_unlock_state();
4289+
if (file_lock)
4290+
locks_free_lock(file_lock);
42664291
return status;
42674292
}
42684293

@@ -4272,7 +4297,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
42724297
{
42734298
struct nfs4_ol_stateid *stp;
42744299
struct file *filp = NULL;
4275-
struct file_lock file_lock;
4300+
struct file_lock *file_lock = NULL;
42764301
__be32 status;
42774302
int err;
42784303

@@ -4294,22 +4319,29 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
42944319
status = nfserr_lock_range;
42954320
goto out;
42964321
}
4297-
locks_init_lock(&file_lock);
4298-
file_lock.fl_type = F_UNLCK;
4299-
file_lock.fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
4300-
file_lock.fl_pid = current->tgid;
4301-
file_lock.fl_file = filp;
4302-
file_lock.fl_flags = FL_POSIX;
4303-
file_lock.fl_lmops = &nfsd_posix_mng_ops;
4304-
file_lock.fl_start = locku->lu_offset;
4305-
4306-
file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length);
4307-
nfs4_transform_lock_offset(&file_lock);
4322+
file_lock = locks_alloc_lock();
4323+
if (!file_lock) {
4324+
dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4325+
status = nfserr_jukebox;
4326+
goto out;
4327+
}
4328+
locks_init_lock(file_lock);
4329+
file_lock->fl_type = F_UNLCK;
4330+
file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
4331+
file_lock->fl_pid = current->tgid;
4332+
file_lock->fl_file = filp;
4333+
file_lock->fl_flags = FL_POSIX;
4334+
file_lock->fl_lmops = &nfsd_posix_mng_ops;
4335+
file_lock->fl_start = locku->lu_offset;
4336+
4337+
file_lock->fl_end = last_byte_offset(locku->lu_offset,
4338+
locku->lu_length);
4339+
nfs4_transform_lock_offset(file_lock);
43084340

43094341
/*
43104342
* Try to unlock the file in the VFS.
43114343
*/
4312-
err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL);
4344+
err = vfs_lock_file(filp, F_SETLK, file_lock, NULL);
43134345
if (err) {
43144346
dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
43154347
goto out_nfserr;
@@ -4323,6 +4355,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
43234355
out:
43244356
if (!cstate->replay_owner)
43254357
nfs4_unlock_state();
4358+
if (file_lock)
4359+
locks_free_lock(file_lock);
43264360
return status;
43274361

43284362
out_nfserr:

0 commit comments

Comments
 (0)