Commit cf430fc8 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] Track nfsv4 open files by "struct inode" rather than dev/ino/generation

parent 505ec28d
...@@ -688,7 +688,7 @@ static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; ...@@ -688,7 +688,7 @@ static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
#define OPENSTATEID_HASH_MASK (OPENSTATEID_HASH_SIZE - 1) #define OPENSTATEID_HASH_MASK (OPENSTATEID_HASH_SIZE - 1)
#define file_hashval(x) \ #define file_hashval(x) \
((unsigned int)((x)->dev + (x)->ino + (x)->generation) & FILE_HASH_MASK) hash_ptr(x, FILE_HASH_BITS)
#define openstateid_hashval(owner_id, file_id) \ #define openstateid_hashval(owner_id, file_id) \
(((owner_id) + (file_id)) & OPENSTATEID_HASH_MASK) (((owner_id) + (file_id)) & OPENSTATEID_HASH_MASK)
...@@ -697,13 +697,13 @@ static struct list_head openstateid_hashtbl[OPENSTATEID_HASH_SIZE]; ...@@ -697,13 +697,13 @@ static struct list_head openstateid_hashtbl[OPENSTATEID_HASH_SIZE];
/* OPEN Share state helper functions */ /* OPEN Share state helper functions */
static inline struct nfs4_file * static inline struct nfs4_file *
alloc_init_file(unsigned int hashval, nfs4_ino_desc_t *ino) { alloc_init_file(unsigned int hashval, struct inode *ino) {
struct nfs4_file *fp; struct nfs4_file *fp;
if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) { if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
INIT_LIST_HEAD(&fp->fi_hash); INIT_LIST_HEAD(&fp->fi_hash);
INIT_LIST_HEAD(&fp->fi_perfile); INIT_LIST_HEAD(&fp->fi_perfile);
list_add(&fp->fi_hash, &file_hashtbl[hashval]); list_add(&fp->fi_hash, &file_hashtbl[hashval]);
memcpy(&fp->fi_ino, ino, sizeof(nfs4_ino_desc_t)); fp->fi_ino = igrab(ino);
fp->fi_id = current_fileid++; fp->fi_id = current_fileid++;
alloc_file++; alloc_file++;
return fp; return fp;
...@@ -841,6 +841,7 @@ release_file(struct nfs4_file *fp) ...@@ -841,6 +841,7 @@ release_file(struct nfs4_file *fp)
{ {
free_file++; free_file++;
list_del_init(&fp->fi_hash); list_del_init(&fp->fi_hash);
iput(fp->ino);
kfree(fp); kfree(fp);
} }
...@@ -934,24 +935,10 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) { ...@@ -934,24 +935,10 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
return 1; return 1;
} }
static inline void
nfs4_init_ino(nfs4_ino_desc_t *ino, struct svc_fh *fhp)
{
struct inode *inode;
if (!fhp->fh_dentry)
BUG();
inode = fhp->fh_dentry->d_inode;
if (!inode)
BUG();
ino->dev = inode->i_sb->s_dev;
ino->ino = inode->i_ino;
ino->generation = inode->i_generation;
}
int int
nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
{ {
nfs4_ino_desc_t ino; struct inode *ino = current_fh->fh_dentry->d_inode;
unsigned int fi_hashval; unsigned int fi_hashval;
struct nfs4_file *fp; struct nfs4_file *fp;
struct nfs4_stateid *stp; struct nfs4_stateid *stp;
...@@ -959,9 +946,8 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) ...@@ -959,9 +946,8 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
dprintk("NFSD: nfs4_share_conflict\n"); dprintk("NFSD: nfs4_share_conflict\n");
nfs4_init_ino(&ino, current_fh); fi_hashval = file_hashval(ino);
fi_hashval = file_hashval(&ino); if (find_file(fi_hashval, ino, &fp)) {
if (find_file(fi_hashval, &ino, &fp)) {
/* Search for conflicting share reservations */ /* Search for conflicting share reservations */
list_for_each_safe(pos, next, &fp->fi_perfile) { list_for_each_safe(pos, next, &fp->fi_perfile) {
stp = list_entry(pos, struct nfs4_stateid, st_perfile); stp = list_entry(pos, struct nfs4_stateid, st_perfile);
...@@ -1084,7 +1070,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf ...@@ -1084,7 +1070,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
struct iattr iattr; struct iattr iattr;
struct nfs4_stateowner *sop = open->op_stateowner; struct nfs4_stateowner *sop = open->op_stateowner;
struct nfs4_file *fp; struct nfs4_file *fp;
nfs4_ino_desc_t ino; struct inode *ino;
unsigned int fi_hashval; unsigned int fi_hashval;
struct list_head *pos, *next; struct list_head *pos, *next;
struct nfs4_stateid *stq, *stp = NULL; struct nfs4_stateid *stq, *stp = NULL;
...@@ -1094,11 +1080,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf ...@@ -1094,11 +1080,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
if (!sop) if (!sop)
goto out; goto out;
nfs4_init_ino(&ino, current_fh); ino = current_fh->fh_dentry->d_inode;
down(&client_sema); /*XXX need finer grained locking */ down(&client_sema); /*XXX need finer grained locking */
fi_hashval = file_hashval(&ino); fi_hashval = file_hashval(ino);
if (find_file(fi_hashval, &ino, &fp)) { if (find_file(fi_hashval, ino, &fp)) {
/* Search for conflicting share reservations */ /* Search for conflicting share reservations */
status = nfserr_share_denied; status = nfserr_share_denied;
list_for_each_safe(pos, next, &fp->fi_perfile) { list_for_each_safe(pos, next, &fp->fi_perfile) {
...@@ -1113,7 +1099,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf ...@@ -1113,7 +1099,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
} else { } else {
/* No nfs4_file found; allocate and init a new one */ /* No nfs4_file found; allocate and init a new one */
status = nfserr_resource; status = nfserr_resource;
if ((fp = alloc_init_file(fi_hashval, &ino)) == NULL) if ((fp = alloc_init_file(fi_hashval, ino)) == NULL)
goto out; goto out;
} }
...@@ -1172,6 +1158,9 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf ...@@ -1172,6 +1158,9 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
status = nfs_ok; status = nfs_ok;
out: out:
if (fp && list_empty(&fp->fi_perfile))
release_file(fp);
/* /*
* To finish the open response, we just need to set the rflags. * To finish the open response, we just need to set the rflags.
*/ */
......
...@@ -113,21 +113,15 @@ struct nfs4_stateowner { ...@@ -113,21 +113,15 @@ struct nfs4_stateowner {
int so_confirmed; /* successful OPEN_CONFIRM? */ int so_confirmed; /* successful OPEN_CONFIRM? */
}; };
typedef struct {
u32 dev; /* super_block->s_dev */
unsigned long ino;
u32 generation;
} nfs4_ino_desc_t;
/* /*
* nfs4_file: a file opened by some number of (open) nfs4_stateowners. * nfs4_file: a file opened by some number of (open) nfs4_stateowners.
* o fi_perfile list is used to search for conflicting * o fi_perfile list is used to search for conflicting
* share_acces, share_deny on the file. * share_acces, share_deny on the file.
*/ */
struct nfs4_file { struct nfs4_file {
struct list_head fi_hash; /* hash by nfs4_ino_desc_t fields */ struct list_head fi_hash; /* hash by "struct inode *" */
struct list_head fi_perfile; /* list: nfs4_stateid */ struct list_head fi_perfile; /* list: nfs4_stateid */
nfs4_ino_desc_t fi_ino; struct inode *fi_inode;
u32 fi_id; /* used with stateowner->so_id u32 fi_id; /* used with stateowner->so_id
* for openstateid_hashtbl hash */ * for openstateid_hashtbl hash */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment