aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-08-21 08:03:32 -0400
committerJ. Bruce Fields <bfields@redhat.com>2012-08-21 14:08:39 -0400
commit21179d81f1de37c93435dce10d2a4378c370ecca (patch)
tree1e98dee111af862b69e1dd190cc97974a0b4e6e8 /fs/nfsd
parent5592a3f3978c57175ef817a4f773bc0d6d8949b9 (diff)
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>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c118
1 files changed, 76 insertions, 42 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 123b47105c0d..5f1a91a9cd35 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4046,8 +4046,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4046 struct nfs4_lockowner *lock_sop = NULL; 4046 struct nfs4_lockowner *lock_sop = NULL;
4047 struct nfs4_ol_stateid *lock_stp; 4047 struct nfs4_ol_stateid *lock_stp;
4048 struct file *filp = NULL; 4048 struct file *filp = NULL;
4049 struct file_lock file_lock; 4049 struct file_lock *file_lock = NULL;
4050 struct file_lock conflock; 4050 struct file_lock *conflock = NULL;
4051 __be32 status = 0; 4051 __be32 status = 0;
4052 bool new_state = false; 4052 bool new_state = false;
4053 int lkflg; 4053 int lkflg;
@@ -4117,21 +4117,28 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4117 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim) 4117 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
4118 goto out; 4118 goto out;
4119 4119
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);
4121 switch (lock->lk_type) { 4128 switch (lock->lk_type) {
4122 case NFS4_READ_LT: 4129 case NFS4_READ_LT:
4123 case NFS4_READW_LT: 4130 case NFS4_READW_LT:
4124 filp = find_readable_file(lock_stp->st_file); 4131 filp = find_readable_file(lock_stp->st_file);
4125 if (filp) 4132 if (filp)
4126 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); 4133 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
4127 file_lock.fl_type = F_RDLCK; 4134 file_lock->fl_type = F_RDLCK;
4128 break; 4135 break;
4129 case NFS4_WRITE_LT: 4136 case NFS4_WRITE_LT:
4130 case NFS4_WRITEW_LT: 4137 case NFS4_WRITEW_LT:
4131 filp = find_writeable_file(lock_stp->st_file); 4138 filp = find_writeable_file(lock_stp->st_file);
4132 if (filp) 4139 if (filp)
4133 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); 4140 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
4134 file_lock.fl_type = F_WRLCK; 4141 file_lock->fl_type = F_WRLCK;
4135 break; 4142 break;
4136 default: 4143 default:
4137 status = nfserr_inval; 4144 status = nfserr_inval;
@@ -4141,17 +4148,23 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4141 status = nfserr_openmode; 4148 status = nfserr_openmode;
4142 goto out; 4149 goto out;
4143 } 4150 }
4144 file_lock.fl_owner = (fl_owner_t)lock_sop; 4151 file_lock->fl_owner = (fl_owner_t)lock_sop;
4145 file_lock.fl_pid = current->tgid; 4152 file_lock->fl_pid = current->tgid;
4146 file_lock.fl_file = filp; 4153 file_lock->fl_file = filp;
4147 file_lock.fl_flags = FL_POSIX; 4154 file_lock->fl_flags = FL_POSIX;
4148 file_lock.fl_lmops = &nfsd_posix_mng_ops; 4155 file_lock->fl_lmops = &nfsd_posix_mng_ops;
4149 4156 file_lock->fl_start = lock->lk_offset;
4150 file_lock.fl_start = lock->lk_offset; 4157 file_lock->fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
4151 file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); 4158 nfs4_transform_lock_offset(file_lock);
4152 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 }
4153 4166
4154 err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock); 4167 err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
4155 switch (-err) { 4168 switch (-err) {
4156 case 0: /* success! */ 4169 case 0: /* success! */
4157 update_stateid(&lock_stp->st_stid.sc_stateid); 4170 update_stateid(&lock_stp->st_stid.sc_stateid);
@@ -4162,7 +4175,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4162 case (EAGAIN): /* conflock holds conflicting lock */ 4175 case (EAGAIN): /* conflock holds conflicting lock */
4163 status = nfserr_denied; 4176 status = nfserr_denied;
4164 dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); 4177 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);
4166 break; 4179 break;
4167 case (EDEADLK): 4180 case (EDEADLK):
4168 status = nfserr_deadlock; 4181 status = nfserr_deadlock;
@@ -4177,6 +4190,10 @@ out:
4177 release_lockowner(lock_sop); 4190 release_lockowner(lock_sop);
4178 if (!cstate->replay_owner) 4191 if (!cstate->replay_owner)
4179 nfs4_unlock_state(); 4192 nfs4_unlock_state();
4193 if (file_lock)
4194 locks_free_lock(file_lock);
4195 if (conflock)
4196 locks_free_lock(conflock);
4180 return status; 4197 return status;
4181} 4198}
4182 4199
@@ -4205,7 +4222,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4205 struct nfsd4_lockt *lockt) 4222 struct nfsd4_lockt *lockt)
4206{ 4223{
4207 struct inode *inode; 4224 struct inode *inode;
4208 struct file_lock file_lock; 4225 struct file_lock *file_lock = NULL;
4209 struct nfs4_lockowner *lo; 4226 struct nfs4_lockowner *lo;
4210 __be32 status; 4227 __be32 status;
4211 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 4228 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,
4226 goto out; 4243 goto out;
4227 4244
4228 inode = cstate->current_fh.fh_dentry->d_inode; 4245 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);
4230 switch (lockt->lt_type) { 4253 switch (lockt->lt_type) {
4231 case NFS4_READ_LT: 4254 case NFS4_READ_LT:
4232 case NFS4_READW_LT: 4255 case NFS4_READW_LT:
4233 file_lock.fl_type = F_RDLCK; 4256 file_lock->fl_type = F_RDLCK;
4234 break; 4257 break;
4235 case NFS4_WRITE_LT: 4258 case NFS4_WRITE_LT:
4236 case NFS4_WRITEW_LT: 4259 case NFS4_WRITEW_LT:
4237 file_lock.fl_type = F_WRLCK; 4260 file_lock->fl_type = F_WRLCK;
4238 break; 4261 break;
4239 default: 4262 default:
4240 dprintk("NFSD: nfs4_lockt: bad lock type!\n"); 4263 dprintk("NFSD: nfs4_lockt: bad lock type!\n");
@@ -4244,25 +4267,27 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4244 4267
4245 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner); 4268 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner);
4246 if (lo) 4269 if (lo)
4247 file_lock.fl_owner = (fl_owner_t)lo; 4270 file_lock->fl_owner = (fl_owner_t)lo;
4248 file_lock.fl_pid = current->tgid; 4271 file_lock->fl_pid = current->tgid;
4249 file_lock.fl_flags = FL_POSIX; 4272 file_lock->fl_flags = FL_POSIX;
4250 4273
4251 file_lock.fl_start = lockt->lt_offset; 4274 file_lock->fl_start = lockt->lt_offset;
4252 file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); 4275 file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
4253 4276
4254 nfs4_transform_lock_offset(&file_lock); 4277 nfs4_transform_lock_offset(file_lock);
4255 4278
4256 status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); 4279 status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock);
4257 if (status) 4280 if (status)
4258 goto out; 4281 goto out;
4259 4282
4260 if (file_lock.fl_type != F_UNLCK) { 4283 if (file_lock->fl_type != F_UNLCK) {
4261 status = nfserr_denied; 4284 status = nfserr_denied;
4262 nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); 4285 nfs4_set_lock_denied(file_lock, &lockt->lt_denied);
4263 } 4286 }
4264out: 4287out:
4265 nfs4_unlock_state(); 4288 nfs4_unlock_state();
4289 if (file_lock)
4290 locks_free_lock(file_lock);
4266 return status; 4291 return status;
4267} 4292}
4268 4293
@@ -4272,7 +4297,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4272{ 4297{
4273 struct nfs4_ol_stateid *stp; 4298 struct nfs4_ol_stateid *stp;
4274 struct file *filp = NULL; 4299 struct file *filp = NULL;
4275 struct file_lock file_lock; 4300 struct file_lock *file_lock = NULL;
4276 __be32 status; 4301 __be32 status;
4277 int err; 4302 int err;
4278 4303
@@ -4294,22 +4319,29 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4294 status = nfserr_lock_range; 4319 status = nfserr_lock_range;
4295 goto out; 4320 goto out;
4296 } 4321 }
4297 locks_init_lock(&file_lock); 4322 file_lock = locks_alloc_lock();
4298 file_lock.fl_type = F_UNLCK; 4323 if (!file_lock) {
4299 file_lock.fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); 4324 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4300 file_lock.fl_pid = current->tgid; 4325 status = nfserr_jukebox;
4301 file_lock.fl_file = filp; 4326 goto out;
4302 file_lock.fl_flags = FL_POSIX; 4327 }
4303 file_lock.fl_lmops = &nfsd_posix_mng_ops; 4328 locks_init_lock(file_lock);
4304 file_lock.fl_start = locku->lu_offset; 4329 file_lock->fl_type = F_UNLCK;
4305 4330 file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
4306 file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length); 4331 file_lock->fl_pid = current->tgid;
4307 nfs4_transform_lock_offset(&file_lock); 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);
4308 4340
4309 /* 4341 /*
4310 * Try to unlock the file in the VFS. 4342 * Try to unlock the file in the VFS.
4311 */ 4343 */
4312 err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL); 4344 err = vfs_lock_file(filp, F_SETLK, file_lock, NULL);
4313 if (err) { 4345 if (err) {
4314 dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n"); 4346 dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
4315 goto out_nfserr; 4347 goto out_nfserr;
@@ -4323,6 +4355,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4323out: 4355out:
4324 if (!cstate->replay_owner) 4356 if (!cstate->replay_owner)
4325 nfs4_unlock_state(); 4357 nfs4_unlock_state();
4358 if (file_lock)
4359 locks_free_lock(file_lock);
4326 return status; 4360 return status;
4327 4361
4328out_nfserr: 4362out_nfserr: