X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fnfsd%2Fnfs4state.c;h=1ca8ce8f6680bb5b0741657473190d680ee2c574;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=0ff4425cae9aba831f9817097411cca09408ecf5;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 0ff4425ca..1ca8ce8f6 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -236,7 +236,7 @@ static struct nfs4_client * create_client(struct xdr_netobj name) { struct nfs4_client *clp; - if(!(clp = alloc_client(name))) + if (!(clp = alloc_client(name))) goto out; INIT_LIST_HEAD(&clp->cl_idhash); INIT_LIST_HEAD(&clp->cl_strhash); @@ -268,7 +268,7 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) { static int cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) { - if(!n1 || !n2) + if (!n1 || !n2) return 0; return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len)); } @@ -399,7 +399,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne return 0; } cbaddr |= (temp << shift); - if(shift > 0) + if (shift > 0) shift -= 8; } *cbaddrp = cbaddr; @@ -411,7 +411,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne return 0; } cbport |= (temp << shift); - if(shift > 0) + if (shift > 0) shift -= 8; } *cbportp = cbport; @@ -423,7 +423,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) { struct nfs4_callback *cb = &clp->cl_callback; - if( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val, + if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val, &cb->cb_addr, &cb->cb_port))) { printk(KERN_INFO "NFSD: BAD callback address. client will not receive delegations\n"); cb->cb_parsed = 0; @@ -431,9 +431,9 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) } cb->cb_netid.len = se->se_callback_netid_len; cb->cb_netid.data = se->se_callback_netid_val; - cb->cb_prog = se->se_callback_prog; - cb->cb_ident = se->se_callback_ident; - cb->cb_parsed = 1; + cb->cb_prog = se->se_callback_prog; + cb->cb_ident = se->se_callback_ident; + cb->cb_parsed = 1; } /* @@ -812,7 +812,7 @@ alloc_init_file(unsigned int hashval, struct inode *ino) { alloc_file++; return fp; } - return (struct nfs4_file *)NULL; + return NULL; } static void @@ -825,7 +825,7 @@ release_all_files(void) while (!list_empty(&file_hashtbl[i])) { fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash); /* this should never be more than once... */ - if(!list_empty(&fp->fi_perfile)) { + if (!list_empty(&fp->fi_perfile)) { printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp); } release_file(fp); @@ -839,20 +839,20 @@ alloc_stateowner(struct xdr_netobj *owner) struct nfs4_stateowner *sop; if ((sop = kmalloc(sizeof(struct nfs4_stateowner),GFP_KERNEL))) { - if((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) { + if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) { memcpy(sop->so_owner.data, owner->data, owner->len); sop->so_owner.len = owner->len; return sop; } kfree(sop); } - return (struct nfs4_stateowner *)NULL; + return NULL; } /* should use a slab cache */ static void free_stateowner(struct nfs4_stateowner *sop) { - if(sop) { + if (sop) { kfree(sop->so_owner.data); kfree(sop); sop = NULL; @@ -867,7 +867,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str unsigned int idhashval; if (!(sop = alloc_stateowner(&open->op_owner))) - return (struct nfs4_stateowner *)NULL; + return NULL; idhashval = ownerid_hashval(current_ownerid); INIT_LIST_HEAD(&sop->so_idhash); INIT_LIST_HEAD(&sop->so_strhash); @@ -908,7 +908,7 @@ release_stateid_lockowner(struct nfs4_stateid *open_stp) } static void -release_stateowner(struct nfs4_stateowner *sop) +unhash_stateowner(struct nfs4_stateowner *sop) { struct nfs4_stateid *stp; @@ -916,16 +916,22 @@ release_stateowner(struct nfs4_stateowner *sop) list_del(&sop->so_strhash); list_del(&sop->so_perclient); list_del(&sop->so_perlockowner); - list_del(&sop->so_close_lru); del_perclient++; while (!list_empty(&sop->so_perfilestate)) { stp = list_entry(sop->so_perfilestate.next, struct nfs4_stateid, st_perfilestate); - if(sop->so_is_open_owner) + if (sop->so_is_open_owner) release_stateid(stp, OPEN_STATE); else release_stateid(stp, LOCK_STATE); } +} + +static void +release_stateowner(struct nfs4_stateowner *sop) +{ + unhash_stateowner(sop); + list_del(&sop->so_close_lru); free_stateowner(sop); } @@ -960,14 +966,12 @@ release_stateid(struct nfs4_stateid *stp, int flags) { list_del_perfile++; list_del(&stp->st_perfile); list_del(&stp->st_perfilestate); - if((stp->st_vfs_set) && (flags & OPEN_STATE)) { + if ((stp->st_vfs_set) && (flags & OPEN_STATE)) { release_stateid_lockowner(stp); - nfsd_close(&stp->st_vfs_file); + nfsd_close(stp->st_vfs_file); vfsclose++; - dput(stp->st_vfs_file.f_dentry); - mntput(stp->st_vfs_file.f_vfsmnt); } else if ((stp->st_vfs_set) && (flags & LOCK_STATE)) { - struct file *filp = &stp->st_vfs_file; + struct file *filp = stp->st_vfs_file; locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); } @@ -988,13 +992,10 @@ void move_to_close_lru(struct nfs4_stateowner *sop) { dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop); - /* remove stateowner from all other hash lists except perclient */ - list_del_init(&sop->so_idhash); - list_del_init(&sop->so_strhash); - list_del_init(&sop->so_perlockowner); - list_add_tail(&sop->so_close_lru, &close_lru); - sop->so_time = get_seconds(); + unhash_stateowner(sop); + list_add_tail(&sop->so_close_lru, &close_lru); + sop->so_time = get_seconds(); } void @@ -1032,7 +1033,7 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, struct nf struct nfs4_stateowner *local = NULL; list_for_each_entry(local, &ownerstr_hashtbl[hashval], so_strhash) { - if(!cmp_owner_str(local, &open->op_owner, &open->op_clientid)) + if (!cmp_owner_str(local, &open->op_owner, &open->op_clientid)) continue; *op = local; return(1); @@ -1080,7 +1081,7 @@ set_access(unsigned int *access, unsigned long bmap) { *access = 0; for (i = 1; i < 4; i++) { - if(test_bit(i, &bmap)) + if (test_bit(i, &bmap)) *access |= i; } } @@ -1091,7 +1092,7 @@ set_deny(unsigned int *deny, unsigned long bmap) { *deny = 0; for (i = 0; i < 4; i++) { - if(test_bit(i, &bmap)) + if (test_bit(i, &bmap)) *deny |= i ; } } @@ -1280,7 +1281,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf /* Search for conflicting share reservations */ status = nfserr_share_denied; list_for_each_entry(stq, &fp->fi_perfile, st_perfile) { - if(stq->st_stateowner == sop) { + if (stq->st_stateowner == sop) { stp = stq; continue; } @@ -1315,8 +1316,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf goto out_free; vfsopen++; - dget(stp->st_vfs_file.f_dentry); - mntget(stp->st_vfs_file.f_vfsmnt); init_stateid(stp, fp, sop, open); stp->st_vfs_set = 1; @@ -1331,7 +1330,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf share_access &= open->op_share_access; /* update the struct file */ - if ((status = nfs4_file_upgrade(&stp->st_vfs_file, share_access))) + if ((status = nfs4_file_upgrade(stp->st_vfs_file, share_access))) goto out; /* remember the open */ set_bit(open->op_share_access, &stp->st_access_bmap); @@ -1460,7 +1459,8 @@ nfs4_laundromat(void) } dprintk("NFSD: purging unused open stateowner (so_id %d)\n", sop->so_id); - release_stateowner(sop); + list_del(&sop->so_close_lru); + free_stateowner(sop); } if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT) clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT; @@ -1488,7 +1488,7 @@ find_openstateowner_id(u32 st_id, int flags) { dprintk("NFSD: find_openstateowner_id %d\n", st_id); if (flags & CLOSE_STATE) { list_for_each_entry(local, &close_lru, so_close_lru) { - if(local->so_id == st_id) + if (local->so_id == st_id) return local; } } @@ -1499,7 +1499,7 @@ static inline int nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp) { return (stp->st_vfs_set == 0 || - fhp->fh_dentry->d_inode != stp->st_vfs_file.f_dentry->d_inode); + fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode); } static int @@ -1816,7 +1816,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n goto out; } set_access(&share_access, stp->st_access_bmap); - nfs4_file_downgrade(&stp->st_vfs_file, + nfs4_file_downgrade(stp->st_vfs_file, share_access & ~od->od_share_access); reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap); @@ -1892,16 +1892,16 @@ find_stateid(stateid_t *stid, int flags) if ((flags & LOCK_STATE) || (flags & RDWR_STATE)) { hashval = stateid_hashval(st_id, f_id); list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) { - if((local->st_stateid.si_stateownerid == st_id) && - (local->st_stateid.si_fileid == f_id)) + if ((local->st_stateid.si_stateownerid == st_id) && + (local->st_stateid.si_fileid == f_id)) return local; } } if ((flags & OPEN_STATE) || (flags & RDWR_STATE)) { hashval = stateid_hashval(st_id, f_id); list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) { - if((local->st_stateid.si_stateownerid == st_id) && - (local->st_stateid.si_fileid == f_id)) + if ((local->st_stateid.si_stateownerid == st_id) && + (local->st_stateid.si_fileid == f_id)) return local; } } else @@ -1950,9 +1950,10 @@ static inline void nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) { struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner; + unsigned int hval = lockownerid_hashval(sop->so_id); deny->ld_sop = NULL; - if (nfs4_verify_lock_stateowner(sop, fl->fl_pid)) + if (nfs4_verify_lock_stateowner(sop, hval)) deny->ld_sop = sop; deny->ld_start = fl->fl_start; deny->ld_length = ~(u64)0; @@ -1971,7 +1972,7 @@ find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid) for (i = 0; i < LOCK_HASH_SIZE; i++) { list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) { - if(!cmp_owner_str(local, owner, clid)) + if (!cmp_owner_str(local, owner, clid)) continue; return local; } @@ -1984,7 +1985,7 @@ find_lockstateowner_str(unsigned int hashval, struct xdr_netobj *owner, clientid struct nfs4_stateowner *local = NULL; list_for_each_entry(local, &lock_ownerstr_hashtbl[hashval], so_strhash) { - if(!cmp_owner_str(local, owner, clid)) + if (!cmp_owner_str(local, owner, clid)) continue; *op = local; return(1); @@ -2009,7 +2010,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str unsigned int idhashval; if (!(sop = alloc_stateowner(&lock->lk_new_owner))) - return (struct nfs4_stateowner *)NULL; + return NULL; idhashval = lockownerid_hashval(current_ownerid); INIT_LIST_HEAD(&sop->so_idhash); INIT_LIST_HEAD(&sop->so_strhash); @@ -2059,7 +2060,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc stp->st_stateid.si_stateownerid = sop->so_id; stp->st_stateid.si_fileid = fp->fi_id; stp->st_stateid.si_generation = 0; - stp->st_vfs_file = open_stp->st_vfs_file; + stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */ stp->st_vfs_set = open_stp->st_vfs_set; stp->st_access_bmap = open_stp->st_access_bmap; stp->st_deny_bmap = open_stp->st_deny_bmap; @@ -2072,7 +2073,7 @@ int check_lock_length(u64 offset, u64 length) { return ((length == 0) || ((length != ~(u64)0) && - LOFF_OVERFLOW(offset, length))); + LOFF_OVERFLOW(offset, length))); } /* @@ -2157,8 +2158,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock))) goto out; if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, - fp, open_stp)) == NULL) + fp, open_stp)) == NULL) { + release_stateowner(lock->lk_stateowner); goto out; + } /* bump the open seqid used to create the lock */ open_sop->so_seqid++; } else { @@ -2172,13 +2175,14 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock goto out; } /* lock->lk_stateowner and lock_stp have been created or found */ - filp = &lock_stp->st_vfs_file; + filp = lock_stp->st_vfs_file; if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) { printk("NFSD: nfsd4_lock: permission denied!\n"); goto out; } + locks_init_lock(&file_lock); switch (lock->lk_type) { case NFS4_READ_LT: case NFS4_READW_LT: @@ -2193,12 +2197,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock goto out; } file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner; - file_lock.fl_pid = lockownerid_hashval(lock->lk_stateowner->so_id); + file_lock.fl_pid = current->tgid; file_lock.fl_file = filp; file_lock.fl_flags = FL_POSIX; - file_lock.fl_notify = NULL; - file_lock.fl_insert = NULL; - file_lock.fl_remove = NULL; file_lock.fl_start = lock->lk_offset; if ((lock->lk_length == ~(u64)0) || @@ -2214,7 +2215,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock */ status = posix_lock_file(filp, &file_lock); - dprintk("NFSD: nfsd4_lock: posix_test_lock passed. posix_lock_file status %d\n",status); + if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) + file_lock.fl_ops->fl_release_private(&file_lock); + dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status); switch (-status) { case 0: /* success! */ update_stateid(&lock_stp->st_stateid); @@ -2265,7 +2268,6 @@ int nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt) { struct inode *inode; - struct nfs4_stateowner *sop; struct file file; struct file_lock file_lock; struct file_lock *conflicting_lock; @@ -2295,6 +2297,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock } inode = current_fh->fh_dentry->d_inode; + locks_init_lock(&file_lock); switch (lockt->lt_type) { case NFS4_READ_LT: case NFS4_READW_LT: @@ -2316,14 +2319,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock find_lockstateowner_str(strhashval, &lockt->lt_owner, &lockt->lt_clientid, &lockt->lt_stateowner); - sop = lockt->lt_stateowner; - if (sop) { - file_lock.fl_owner = (fl_owner_t) sop; - file_lock.fl_pid = lockownerid_hashval(sop->so_id); - } else { - file_lock.fl_owner = NULL; - file_lock.fl_pid = 0; - } + if (lockt->lt_stateowner) + file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner; + file_lock.fl_pid = current->tgid; file_lock.fl_flags = FL_POSIX; file_lock.fl_start = lockt->lt_offset; @@ -2378,16 +2376,14 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock &locku->lu_stateowner, &stp, NULL))) goto out; - filp = &stp->st_vfs_file; + filp = stp->st_vfs_file; BUG_ON(!filp); + locks_init_lock(&file_lock); file_lock.fl_type = F_UNLCK; file_lock.fl_owner = (fl_owner_t) locku->lu_stateowner; - file_lock.fl_pid = lockownerid_hashval(locku->lu_stateowner->so_id); + file_lock.fl_pid = current->tgid; file_lock.fl_file = filp; file_lock.fl_flags = FL_POSIX; - file_lock.fl_notify = NULL; - file_lock.fl_insert = NULL; - file_lock.fl_remove = NULL; file_lock.fl_start = locku->lu_offset; if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length)) @@ -2400,6 +2396,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock * Try to unlock the file in the VFS. */ status = posix_lock_file(filp, &file_lock); + if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private) + file_lock.fl_ops->fl_release_private(&file_lock); if (status) { printk("NFSD: nfs4_locku: posix_lock_file failed!\n"); goto out_nfserr; @@ -2462,7 +2460,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner * nfs4_lock_state(); - status = nfs_ok; + status = nfs_ok; local = find_lockstateowner(owner, clid); if (local) { struct nfs4_stateid *stp; @@ -2472,8 +2470,8 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner * status = nfserr_locks_held; list_for_each_entry(stp, &local->so_perfilestate, st_perfilestate) { - if(stp->st_vfs_set) { - if (check_for_locks(&stp->st_vfs_file, local)) + if (stp->st_vfs_set) { + if (check_for_locks(stp->st_vfs_file, local)) goto out; } } @@ -2499,7 +2497,7 @@ alloc_reclaim(int namelen) kfree(crp); return NULL; } - return crp; + return crp; } /* @@ -2569,7 +2567,7 @@ nfs4_find_reclaim_client(clientid_t *clid) strhashval = clientstr_hashval(client->cl_name.data, client->cl_name.len); list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) { - if(cmp_name(&crp->cr_name, &client->cl_name)) { + if (cmp_name(&crp->cr_name, &client->cl_name)) { return crp; } }