diff options
Diffstat (limited to 'net/sunrpc/cache.c')
| -rw-r--r-- | net/sunrpc/cache.c | 316 | 
1 files changed, 184 insertions, 132 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index e433e7580e2..06636214113 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -37,7 +37,7 @@  #define	 RPCDBG_FACILITY RPCDBG_CACHE -static void cache_defer_req(struct cache_req *req, struct cache_head *item); +static bool cache_defer_req(struct cache_req *req, struct cache_head *item);  static void cache_revisit_request(struct cache_head *item);  static void cache_init(struct cache_head *h) @@ -50,12 +50,6 @@ static void cache_init(struct cache_head *h)  	h->last_refresh = now;  } -static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h) -{ -	return  (h->expiry_time < seconds_since_boot()) || -		(detail->flush_time > h->last_refresh); -} -  struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,  				       struct cache_head *key, int hash)  { @@ -128,6 +122,7 @@ static void cache_fresh_locked(struct cache_head *head, time_t expiry)  {  	head->expiry_time = expiry;  	head->last_refresh = seconds_since_boot(); +	smp_wmb(); /* paired with smp_rmb() in cache_is_valid() */  	set_bit(CACHE_VALID, &head->flags);  } @@ -195,12 +190,12 @@ EXPORT_SYMBOL_GPL(sunrpc_cache_update);  static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h)  { -	if (!cd->cache_upcall) -		return -EINVAL; -	return cd->cache_upcall(cd, h); +	if (cd->cache_upcall) +		return cd->cache_upcall(cd, h); +	return sunrpc_cache_pipe_upcall(cd, h);  } -static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) +static inline int cache_is_valid(struct cache_head *h)  {  	if (!test_bit(CACHE_VALID, &h->flags))  		return -EAGAIN; @@ -208,9 +203,33 @@ static inline int cache_is_valid(struct cache_detail *detail, struct cache_head  		/* entry is valid */  		if (test_bit(CACHE_NEGATIVE, &h->flags))  			return -ENOENT; -		else +		else { +			/* +			 * In combination with write barrier in +			 * sunrpc_cache_update, ensures that anyone +			 * using the cache entry after this sees the +			 * updated contents: +			 */ +			smp_rmb();  			return 0; +		} +	} +} + +static int try_to_negate_entry(struct cache_detail *detail, struct cache_head *h) +{ +	int rv; + +	write_lock(&detail->hash_lock); +	rv = cache_is_valid(h); +	if (rv == -EAGAIN) { +		set_bit(CACHE_NEGATIVE, &h->flags); +		cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY); +		rv = -ENOENT;  	} +	write_unlock(&detail->hash_lock); +	cache_fresh_unlocked(h, detail); +	return rv;  }  /* @@ -234,7 +253,7 @@ int cache_check(struct cache_detail *detail,  	long refresh_age, age;  	/* First decide return status as best we can */ -	rv = cache_is_valid(detail, h); +	rv = cache_is_valid(h);  	/* now see if we want to start an upcall */  	refresh_age = (h->expiry_time - h->last_refresh); @@ -243,35 +262,29 @@ int cache_check(struct cache_detail *detail,  	if (rqstp == NULL) {  		if (rv == -EAGAIN)  			rv = -ENOENT; -	} else if (rv == -EAGAIN || age > refresh_age/2) { +	} else if (rv == -EAGAIN || +		   (h->expiry_time != 0 && age > refresh_age/2)) {  		dprintk("RPC:       Want update, refage=%ld, age=%ld\n",  				refresh_age, age);  		if (!test_and_set_bit(CACHE_PENDING, &h->flags)) {  			switch (cache_make_upcall(detail, h)) {  			case -EINVAL: -				clear_bit(CACHE_PENDING, &h->flags); -				cache_revisit_request(h); -				if (rv == -EAGAIN) { -					set_bit(CACHE_NEGATIVE, &h->flags); -					cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY); -					cache_fresh_unlocked(h, detail); -					rv = -ENOENT; -				} +				rv = try_to_negate_entry(detail, h);  				break; -  			case -EAGAIN: -				clear_bit(CACHE_PENDING, &h->flags); -				cache_revisit_request(h); +				cache_fresh_unlocked(h, detail);  				break;  			}  		}  	}  	if (rv == -EAGAIN) { -		cache_defer_req(rqstp, h); -		if (!test_bit(CACHE_PENDING, &h->flags)) { -			/* Request is not deferred */ -			rv = cache_is_valid(detail, h); +		if (!cache_defer_req(rqstp, h)) { +			/* +			 * Request was not deferred; handle it as best +			 * we can ourselves: +			 */ +			rv = cache_is_valid(h);  			if (rv == -EAGAIN)  				rv = -ETIMEDOUT;  		} @@ -288,7 +301,7 @@ EXPORT_SYMBOL_GPL(cache_check);   * a current pointer into that list and into the table   * for that entry.   * - * Each time clean_cache is called it finds the next non-empty entry + * Each time cache_clean is called it finds the next non-empty entry   * in the current table and walks the list in that entry   * looking for entries that can be removed.   * @@ -322,7 +335,7 @@ static int current_index;  static void do_cache_clean(struct work_struct *work);  static struct delayed_work cache_cleaner; -static void sunrpc_init_cache_detail(struct cache_detail *cd) +void sunrpc_init_cache_detail(struct cache_detail *cd)  {  	rwlock_init(&cd->hash_lock);  	INIT_LIST_HEAD(&cd->queue); @@ -338,8 +351,9 @@ static void sunrpc_init_cache_detail(struct cache_detail *cd)  	/* start the cleaning process */  	schedule_delayed_work(&cache_cleaner, 0);  } +EXPORT_SYMBOL_GPL(sunrpc_init_cache_detail); -static void sunrpc_destroy_cache_detail(struct cache_detail *cd) +void sunrpc_destroy_cache_detail(struct cache_detail *cd)  {  	cache_purge(cd);  	spin_lock(&cache_list_lock); @@ -360,8 +374,9 @@ static void sunrpc_destroy_cache_detail(struct cache_detail *cd)  	}  	return;  out: -	printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); +	printk(KERN_ERR "RPC: failed to unregister %s cache\n", cd->name);  } +EXPORT_SYMBOL_GPL(sunrpc_destroy_cache_detail);  /* clean cache tries to find something to clean   * and cleans it. @@ -433,9 +448,8 @@ static int cache_clean(void)  			current_index ++;  		spin_unlock(&cache_list_lock);  		if (ch) { -			if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) -				cache_dequeue(current_detail, ch); -			cache_revisit_request(ch); +			set_bit(CACHE_CLEANED, &ch->flags); +			cache_fresh_unlocked(ch, d);  			cache_put(ch, d);  		}  	} else @@ -605,7 +619,7 @@ static void cache_limit_defers(void)  	/* Consider removing either the first or the last */  	if (cache_defer_cnt > DFR_MAX) { -		if (net_random() & 1) +		if (prandom_u32() & 1)  			discard = list_entry(cache_defer_list.next,  					     struct cache_deferred_req, recent);  		else @@ -618,18 +632,19 @@ static void cache_limit_defers(void)  		discard->revisit(discard, 1);  } -static void cache_defer_req(struct cache_req *req, struct cache_head *item) +/* Return true if and only if a deferred request is queued. */ +static bool cache_defer_req(struct cache_req *req, struct cache_head *item)  {  	struct cache_deferred_req *dreq;  	if (req->thread_wait) {  		cache_wait_req(req, item);  		if (!test_bit(CACHE_PENDING, &item->flags)) -			return; +			return false;  	}  	dreq = req->defer(req);  	if (dreq == NULL) -		return; +		return false;  	setup_deferral(dreq, item, 1);  	if (!test_bit(CACHE_PENDING, &item->flags))  		/* Bit could have been cleared before we managed to @@ -638,19 +653,20 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)  		cache_revisit_request(item);  	cache_limit_defers(); +	return true;  }  static void cache_revisit_request(struct cache_head *item)  {  	struct cache_deferred_req *dreq;  	struct list_head pending; -	struct hlist_node *lp, *tmp; +	struct hlist_node *tmp;  	int hash = DFR_HASH(item);  	INIT_LIST_HEAD(&pending);  	spin_lock(&cache_defer_lock); -	hlist_for_each_entry_safe(dreq, lp, tmp, &cache_defer_hash[hash], hash) +	hlist_for_each_entry_safe(dreq, tmp, &cache_defer_hash[hash], hash)  		if (dreq->item == item) {  			__unhash_deferred_req(dreq);  			list_add(&dreq->recent, &pending); @@ -724,12 +740,24 @@ struct cache_reader {  	int			offset;	/* if non-0, we have a refcnt on next request */  }; +static int cache_request(struct cache_detail *detail, +			       struct cache_request *crq) +{ +	char *bp = crq->buf; +	int len = PAGE_SIZE; + +	detail->cache_request(detail, crq->item, &bp, &len); +	if (len < 0) +		return -EAGAIN; +	return PAGE_SIZE - len; +} +  static ssize_t cache_read(struct file *filp, char __user *buf, size_t count,  			  loff_t *ppos, struct cache_detail *cd)  {  	struct cache_reader *rp = filp->private_data;  	struct cache_request *rq; -	struct inode *inode = filp->f_path.dentry->d_inode; +	struct inode *inode = file_inode(filp);  	int err;  	if (count == 0) @@ -749,15 +777,22 @@ static ssize_t cache_read(struct file *filp, char __user *buf, size_t count,  	if (rp->q.list.next == &cd->queue) {  		spin_unlock(&queue_lock);  		mutex_unlock(&inode->i_mutex); -		BUG_ON(rp->offset); +		WARN_ON_ONCE(rp->offset);  		return 0;  	}  	rq = container_of(rp->q.list.next, struct cache_request, q.list); -	BUG_ON(rq->q.reader); +	WARN_ON_ONCE(rq->q.reader);  	if (rp->offset == 0)  		rq->readers++;  	spin_unlock(&queue_lock); +	if (rq->len == 0) { +		err = cache_request(cd, rq); +		if (err < 0) +			goto out; +		rq->len = err; +	} +  	if (rp->offset == 0 && !test_bit(CACHE_PENDING, &rq->item->flags)) {  		err = -EAGAIN;  		spin_lock(&queue_lock); @@ -804,6 +839,8 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf,  {  	ssize_t ret; +	if (count == 0) +		return -EINVAL;  	if (copy_from_user(kaddr, buf, count))  		return -EFAULT;  	kaddr[count] = '\0'; @@ -858,7 +895,7 @@ static ssize_t cache_write(struct file *filp, const char __user *buf,  			   struct cache_detail *cd)  {  	struct address_space *mapping = filp->f_mapping; -	struct inode *inode = filp->f_path.dentry->d_inode; +	struct inode *inode = file_inode(filp);  	ssize_t ret = -EINVAL;  	if (!cd->cache_parse) @@ -939,8 +976,10 @@ static int cache_open(struct inode *inode, struct file *filp,  	nonseekable_open(inode, filp);  	if (filp->f_mode & FMODE_READ) {  		rp = kmalloc(sizeof(*rp), GFP_KERNEL); -		if (!rp) +		if (!rp) { +			module_put(cd->owner);  			return -ENOMEM; +		}  		rp->offset = 0;  		rp->q.reader = 1;  		atomic_inc(&cd->readers); @@ -987,23 +1026,32 @@ static int cache_release(struct inode *inode, struct file *filp,  static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch)  { -	struct cache_queue *cq; +	struct cache_queue *cq, *tmp; +	struct cache_request *cr; +	struct list_head dequeued; + +	INIT_LIST_HEAD(&dequeued);  	spin_lock(&queue_lock); -	list_for_each_entry(cq, &detail->queue, list) +	list_for_each_entry_safe(cq, tmp, &detail->queue, list)  		if (!cq->reader) { -			struct cache_request *cr = container_of(cq, struct cache_request, q); +			cr = container_of(cq, struct cache_request, q);  			if (cr->item != ch)  				continue; +			if (test_bit(CACHE_PENDING, &ch->flags)) +				/* Lost a race and it is pending again */ +				break;  			if (cr->readers != 0)  				continue; -			list_del(&cr->q.list); -			spin_unlock(&queue_lock); -			cache_put(cr->item, detail); -			kfree(cr->buf); -			kfree(cr); -			return; +			list_move(&cr->q.list, &dequeued);  		}  	spin_unlock(&queue_lock); +	while (!list_empty(&dequeued)) { +		cr = list_entry(dequeued.next, struct cache_request, q.list); +		list_del(&cr->q.list); +		cache_put(cr->item, detail); +		kfree(cr->buf); +		kfree(cr); +	}  }  /* @@ -1063,9 +1111,7 @@ void qword_addhex(char **bpp, int *lp, char *buf, int blen)  		*bp++ = 'x';  		len -= 2;  		while (blen && len >= 2) { -			unsigned char c = *buf++; -			*bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1); -			*bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1); +			bp = hex_byte_pack(bp, *buf++);  			len -= 2;  			blen--;  		} @@ -1112,22 +1158,23 @@ static bool cache_listeners_exist(struct cache_detail *detail)   *   * Each request is at most one page long.   */ -int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h, -		void (*cache_request)(struct cache_detail *, -				      struct cache_head *, -				      char **, -				      int *)) +int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h)  {  	char *buf;  	struct cache_request *crq; -	char *bp; -	int len; +	int ret = 0; + +	if (!detail->cache_request) +		return -EINVAL;  	if (!cache_listeners_exist(detail)) {  		warn_no_listener(detail);  		return -EINVAL;  	} +	if (test_bit(CACHE_CLEANED, &h->flags)) +		/* Too late to make an upcall */ +		return -EAGAIN;  	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);  	if (!buf) @@ -1139,25 +1186,24 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,  		return -EAGAIN;  	} -	bp = buf; len = PAGE_SIZE; - -	cache_request(detail, h, &bp, &len); - -	if (len < 0) { -		kfree(buf); -		kfree(crq); -		return -EAGAIN; -	}  	crq->q.reader = 0;  	crq->item = cache_get(h);  	crq->buf = buf; -	crq->len = PAGE_SIZE - len; +	crq->len = 0;  	crq->readers = 0;  	spin_lock(&queue_lock); -	list_add_tail(&crq->q.list, &detail->queue); +	if (test_bit(CACHE_PENDING, &h->flags)) +		list_add_tail(&crq->q.list, &detail->queue); +	else +		/* Lost a race, no longer PENDING, so don't enqueue */ +		ret = -EAGAIN;  	spin_unlock(&queue_lock);  	wake_up(&queue_wait); -	return 0; +	if (ret == -EAGAIN) { +		kfree(buf); +		kfree(crq); +	} +	return ret;  }  EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall); @@ -1173,7 +1219,6 @@ EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall);   * key and content are both parsed by cache   */ -#define isodigit(c) (isdigit(c) && c <= '7')  int qword_get(char **bpp, char *dest, int bufsize)  {  	/* return bytes copied, or -1 on error */ @@ -1245,7 +1290,7 @@ static void *c_start(struct seq_file *m, loff_t *pos)  	__acquires(cd->hash_lock)  {  	loff_t n = *pos; -	unsigned hash, entry; +	unsigned int hash, entry;  	struct cache_head *ch;  	struct cache_detail *cd = ((struct handle*)m->private)->cd; @@ -1321,8 +1366,11 @@ static int c_show(struct seq_file *m, void *p)  	if (cache_check(cd, cp, NULL))  		/* cache_check does a cache_put on failure */  		seq_printf(m, "# "); -	else +	else { +		if (cache_is_expired(cd, cp)) +			seq_printf(m, "# ");  		cache_put(cp, cd); +	}  	return cd->cache_show(m, cd, cp);  } @@ -1378,11 +1426,11 @@ static ssize_t read_flush(struct file *file, char __user *buf,  			  size_t count, loff_t *ppos,  			  struct cache_detail *cd)  { -	char tbuf[20]; +	char tbuf[22];  	unsigned long p = *ppos;  	size_t len; -	sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time)); +	snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time));  	len = strlen(tbuf);  	if (p >= len)  		return 0; @@ -1423,7 +1471,7 @@ static ssize_t write_flush(struct file *file, const char __user *buf,  static ssize_t cache_read_procfs(struct file *filp, char __user *buf,  				 size_t count, loff_t *ppos)  { -	struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; +	struct cache_detail *cd = PDE_DATA(file_inode(filp));  	return cache_read(filp, buf, count, ppos, cd);  } @@ -1431,14 +1479,14 @@ static ssize_t cache_read_procfs(struct file *filp, char __user *buf,  static ssize_t cache_write_procfs(struct file *filp, const char __user *buf,  				  size_t count, loff_t *ppos)  { -	struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; +	struct cache_detail *cd = PDE_DATA(file_inode(filp));  	return cache_write(filp, buf, count, ppos, cd);  }  static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait)  { -	struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; +	struct cache_detail *cd = PDE_DATA(file_inode(filp));  	return cache_poll(filp, wait, cd);  } @@ -1446,22 +1494,22 @@ static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait)  static long cache_ioctl_procfs(struct file *filp,  			       unsigned int cmd, unsigned long arg)  { -	struct inode *inode = filp->f_path.dentry->d_inode; -	struct cache_detail *cd = PDE(inode)->data; +	struct inode *inode = file_inode(filp); +	struct cache_detail *cd = PDE_DATA(inode);  	return cache_ioctl(inode, filp, cmd, arg, cd);  }  static int cache_open_procfs(struct inode *inode, struct file *filp)  { -	struct cache_detail *cd = PDE(inode)->data; +	struct cache_detail *cd = PDE_DATA(inode);  	return cache_open(inode, filp, cd);  }  static int cache_release_procfs(struct inode *inode, struct file *filp)  { -	struct cache_detail *cd = PDE(inode)->data; +	struct cache_detail *cd = PDE_DATA(inode);  	return cache_release(inode, filp, cd);  } @@ -1479,14 +1527,14 @@ static const struct file_operations cache_file_operations_procfs = {  static int content_open_procfs(struct inode *inode, struct file *filp)  { -	struct cache_detail *cd = PDE(inode)->data; +	struct cache_detail *cd = PDE_DATA(inode);  	return content_open(inode, filp, cd);  }  static int content_release_procfs(struct inode *inode, struct file *filp)  { -	struct cache_detail *cd = PDE(inode)->data; +	struct cache_detail *cd = PDE_DATA(inode);  	return content_release(inode, filp, cd);  } @@ -1500,14 +1548,14 @@ static const struct file_operations content_file_operations_procfs = {  static int open_flush_procfs(struct inode *inode, struct file *filp)  { -	struct cache_detail *cd = PDE(inode)->data; +	struct cache_detail *cd = PDE_DATA(inode);  	return open_flush(inode, filp, cd);  }  static int release_flush_procfs(struct inode *inode, struct file *filp)  { -	struct cache_detail *cd = PDE(inode)->data; +	struct cache_detail *cd = PDE_DATA(inode);  	return release_flush(inode, filp, cd);  } @@ -1515,7 +1563,7 @@ static int release_flush_procfs(struct inode *inode, struct file *filp)  static ssize_t read_flush_procfs(struct file *filp, char __user *buf,  			    size_t count, loff_t *ppos)  { -	struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; +	struct cache_detail *cd = PDE_DATA(file_inode(filp));  	return read_flush(filp, buf, count, ppos, cd);  } @@ -1524,7 +1572,7 @@ static ssize_t write_flush_procfs(struct file *filp,  				  const char __user *buf,  				  size_t count, loff_t *ppos)  { -	struct cache_detail *cd = PDE(filp->f_path.dentry->d_inode)->data; +	struct cache_detail *cd = PDE_DATA(file_inode(filp));  	return write_flush(filp, buf, count, ppos, cd);  } @@ -1574,7 +1622,7 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)  	if (p == NULL)  		goto out_nomem; -	if (cd->cache_upcall || cd->cache_parse) { +	if (cd->cache_request || cd->cache_parse) {  		p = proc_create_data("channel", S_IFREG|S_IRUSR|S_IWUSR,  				     cd->u.procfs.proc_ent,  				     &cache_file_operations_procfs, cd); @@ -1583,7 +1631,7 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)  			goto out_nomem;  	}  	if (cd->cache_show) { -		p = proc_create_data("content", S_IFREG|S_IRUSR|S_IWUSR, +		p = proc_create_data("content", S_IFREG|S_IRUSR,  				cd->u.procfs.proc_ent,  				&content_file_operations_procfs, cd);  		cd->u.procfs.content_ent = p; @@ -1604,7 +1652,7 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)  void __init cache_initialize(void)  { -	INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean); +	INIT_DEFERRABLE_WORK(&cache_cleaner, do_cache_clean);  }  int cache_register_net(struct cache_detail *cd, struct net *net) @@ -1617,29 +1665,45 @@ int cache_register_net(struct cache_detail *cd, struct net *net)  		sunrpc_destroy_cache_detail(cd);  	return ret;  } - -int cache_register(struct cache_detail *cd) -{ -	return cache_register_net(cd, &init_net); -} -EXPORT_SYMBOL_GPL(cache_register); +EXPORT_SYMBOL_GPL(cache_register_net);  void cache_unregister_net(struct cache_detail *cd, struct net *net)  {  	remove_cache_proc_entries(cd, net);  	sunrpc_destroy_cache_detail(cd);  } +EXPORT_SYMBOL_GPL(cache_unregister_net); + +struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net) +{ +	struct cache_detail *cd; + +	cd = kmemdup(tmpl, sizeof(struct cache_detail), GFP_KERNEL); +	if (cd == NULL) +		return ERR_PTR(-ENOMEM); + +	cd->hash_table = kzalloc(cd->hash_size * sizeof(struct cache_head *), +				 GFP_KERNEL); +	if (cd->hash_table == NULL) { +		kfree(cd); +		return ERR_PTR(-ENOMEM); +	} +	cd->net = net; +	return cd; +} +EXPORT_SYMBOL_GPL(cache_create_net); -void cache_unregister(struct cache_detail *cd) +void cache_destroy_net(struct cache_detail *cd, struct net *net)  { -	cache_unregister_net(cd, &init_net); +	kfree(cd->hash_table); +	kfree(cd);  } -EXPORT_SYMBOL_GPL(cache_unregister); +EXPORT_SYMBOL_GPL(cache_destroy_net);  static ssize_t cache_read_pipefs(struct file *filp, char __user *buf,  				 size_t count, loff_t *ppos)  { -	struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; +	struct cache_detail *cd = RPC_I(file_inode(filp))->private;  	return cache_read(filp, buf, count, ppos, cd);  } @@ -1647,14 +1711,14 @@ static ssize_t cache_read_pipefs(struct file *filp, char __user *buf,  static ssize_t cache_write_pipefs(struct file *filp, const char __user *buf,  				  size_t count, loff_t *ppos)  { -	struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; +	struct cache_detail *cd = RPC_I(file_inode(filp))->private;  	return cache_write(filp, buf, count, ppos, cd);  }  static unsigned int cache_poll_pipefs(struct file *filp, poll_table *wait)  { -	struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; +	struct cache_detail *cd = RPC_I(file_inode(filp))->private;  	return cache_poll(filp, wait, cd);  } @@ -1662,7 +1726,7 @@ static unsigned int cache_poll_pipefs(struct file *filp, poll_table *wait)  static long cache_ioctl_pipefs(struct file *filp,  			      unsigned int cmd, unsigned long arg)  { -	struct inode *inode = filp->f_dentry->d_inode; +	struct inode *inode = file_inode(filp);  	struct cache_detail *cd = RPC_I(inode)->private;  	return cache_ioctl(inode, filp, cmd, arg, cd); @@ -1731,7 +1795,7 @@ static int release_flush_pipefs(struct inode *inode, struct file *filp)  static ssize_t read_flush_pipefs(struct file *filp, char __user *buf,  			    size_t count, loff_t *ppos)  { -	struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; +	struct cache_detail *cd = RPC_I(file_inode(filp))->private;  	return read_flush(filp, buf, count, ppos, cd);  } @@ -1740,7 +1804,7 @@ static ssize_t write_flush_pipefs(struct file *filp,  				  const char __user *buf,  				  size_t count, loff_t *ppos)  { -	struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private; +	struct cache_detail *cd = RPC_I(file_inode(filp))->private;  	return write_flush(filp, buf, count, ppos, cd);  } @@ -1754,25 +1818,14 @@ const struct file_operations cache_flush_operations_pipefs = {  };  int sunrpc_cache_register_pipefs(struct dentry *parent, -				 const char *name, mode_t umode, +				 const char *name, umode_t umode,  				 struct cache_detail *cd)  { -	struct qstr q; -	struct dentry *dir; -	int ret = 0; - -	sunrpc_init_cache_detail(cd); -	q.name = name; -	q.len = strlen(name); -	q.hash = full_name_hash(q.name, q.len); -	dir = rpc_create_cache_dir(parent, &q, umode, cd); -	if (!IS_ERR(dir)) -		cd->u.pipefs.dir = dir; -	else { -		sunrpc_destroy_cache_detail(cd); -		ret = PTR_ERR(dir); -	} -	return ret; +	struct dentry *dir = rpc_create_cache_dir(parent, name, umode, cd); +	if (IS_ERR(dir)) +		return PTR_ERR(dir); +	cd->u.pipefs.dir = dir; +	return 0;  }  EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); @@ -1780,7 +1833,6 @@ void sunrpc_cache_unregister_pipefs(struct cache_detail *cd)  {  	rpc_remove_cache_dir(cd->u.pipefs.dir);  	cd->u.pipefs.dir = NULL; -	sunrpc_destroy_cache_detail(cd);  }  EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs);  | 
