Current File : //usr/src/linux-headers-6.8.0-60-generic/include/linux/fscache.h
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* General filesystem caching interface
 *
 * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * NOTE!!! See:
 *
 *	Documentation/filesystems/caching/netfs-api.rst
 *
 * for a description of the network filesystem interface declared here.
 */

#ifndef _LINUX_FSCACHE_H
#define _LINUX_FSCACHE_H

#include <linux/fs.h>
#include <linux/netfs.h>
#include <linux/writeback.h>

#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
#define __fscache_available (1)
#define fscache_available() (1)
#define fscache_volume_valid(volume) (volume)
#define fscache_cookie_valid(cookie) (cookie)
#define fscache_resources_valid(cres) ((cres)->cache_priv)
#define fscache_cookie_enabled(cookie) (cookie && !test_bit(FSCACHE_COOKIE_DISABLED, &cookie->flags))
#else
#define __fscache_available (0)
#define fscache_available() (0)
#define fscache_volume_valid(volume) (0)
#define fscache_cookie_valid(cookie) (0)
#define fscache_resources_valid(cres) (false)
#define fscache_cookie_enabled(cookie) (0)
#endif

struct fscache_cookie;

#define FSCACHE_ADV_SINGLE_CHUNK	0x01 /* The object is a single chunk of data */
#define FSCACHE_ADV_WRITE_CACHE		0x00 /* Do cache if written to locally */
#define FSCACHE_ADV_WRITE_NOCACHE	0x02 /* Don't cache if written to locally */
#define FSCACHE_ADV_WANT_CACHE_SIZE	0x04 /* Retrieve cache size at runtime */

#define FSCACHE_INVAL_DIO_WRITE		0x01 /* Invalidate due to DIO write */

enum fscache_want_state {
	FSCACHE_WANT_PARAMS,
	FSCACHE_WANT_WRITE,
	FSCACHE_WANT_READ,
};

/*
 * Data object state.
 */
enum fscache_cookie_state {
	FSCACHE_COOKIE_STATE_QUIESCENT,		/* The cookie is uncached */
	FSCACHE_COOKIE_STATE_LOOKING_UP,	/* The cache object is being looked up */
	FSCACHE_COOKIE_STATE_CREATING,		/* The cache object is being created */
	FSCACHE_COOKIE_STATE_ACTIVE,		/* The cache is active, readable and writable */
	FSCACHE_COOKIE_STATE_INVALIDATING,	/* The cache is being invalidated */
	FSCACHE_COOKIE_STATE_FAILED,		/* The cache failed, withdraw to clear */
	FSCACHE_COOKIE_STATE_LRU_DISCARDING,	/* The cookie is being discarded by the LRU */
	FSCACHE_COOKIE_STATE_WITHDRAWING,	/* The cookie is being withdrawn */
	FSCACHE_COOKIE_STATE_RELINQUISHING,	/* The cookie is being relinquished */
	FSCACHE_COOKIE_STATE_DROPPED,		/* The cookie has been dropped */
#define FSCACHE_COOKIE_STATE__NR (FSCACHE_COOKIE_STATE_DROPPED + 1)
} __attribute__((mode(byte)));

/*
 * Volume representation cookie.
 */
struct fscache_volume {
	refcount_t			ref;
	atomic_t			n_cookies;	/* Number of data cookies in volume */
	atomic_t			n_accesses;	/* Number of cache accesses in progress */
	unsigned int			debug_id;
	unsigned int			key_hash;	/* Hash of key string */
	u8				*key;		/* Volume ID, eg. "afs@example.com@1234" */
	struct list_head		proc_link;	/* Link in /proc/fs/fscache/volumes */
	struct hlist_bl_node		hash_link;	/* Link in hash table */
	struct work_struct		work;
	struct fscache_cache		*cache;		/* The cache in which this resides */
	void				*cache_priv;	/* Cache private data */
	spinlock_t			lock;
	unsigned long			flags;
#define FSCACHE_VOLUME_RELINQUISHED	0	/* Volume is being cleaned up */
#define FSCACHE_VOLUME_INVALIDATE	1	/* Volume was invalidated */
#define FSCACHE_VOLUME_COLLIDED_WITH	2	/* Volume was collided with */
#define FSCACHE_VOLUME_ACQUIRE_PENDING	3	/* Volume is waiting to complete acquisition */
#define FSCACHE_VOLUME_CREATING		4	/* Volume is being created on disk */
	u8				coherency_len;	/* Length of the coherency data */
	u8				coherency[];	/* Coherency data */
};

/*
 * Data file representation cookie.
 * - a file will only appear in one cache
 * - a request to cache a file may or may not be honoured, subject to
 *   constraints such as disk space
 * - indices are created on disk just-in-time
 */
struct fscache_cookie {
	refcount_t			ref;
	atomic_t			n_active;	/* number of active users of cookie */
	atomic_t			n_accesses;	/* Number of cache accesses in progress */
	unsigned int			debug_id;
	unsigned int			inval_counter;	/* Number of invalidations made */
	spinlock_t			lock;
	struct fscache_volume		*volume;	/* Parent volume of this file. */
	void				*cache_priv;	/* Cache-side representation */
	struct hlist_bl_node		hash_link;	/* Link in hash table */
	struct list_head		proc_link;	/* Link in proc list */
	struct list_head		commit_link;	/* Link in commit queue */
	struct work_struct		work;		/* Commit/relinq/withdraw work */
	loff_t				object_size;	/* Size of the netfs object */
	unsigned long			unused_at;	/* Time at which unused (jiffies) */
	unsigned long			flags;
#define FSCACHE_COOKIE_RELINQUISHED	0		/* T if cookie has been relinquished */
#define FSCACHE_COOKIE_RETIRED		1		/* T if this cookie has retired on relinq */
#define FSCACHE_COOKIE_IS_CACHING	2		/* T if this cookie is cached */
#define FSCACHE_COOKIE_NO_DATA_TO_READ	3		/* T if this cookie has nothing to read */
#define FSCACHE_COOKIE_NEEDS_UPDATE	4		/* T if attrs have been updated */
#define FSCACHE_COOKIE_HAS_BEEN_CACHED	5		/* T if cookie needs withdraw-on-relinq */
#define FSCACHE_COOKIE_DISABLED		6		/* T if cookie has been disabled */
#define FSCACHE_COOKIE_LOCAL_WRITE	7		/* T if cookie has been modified locally */
#define FSCACHE_COOKIE_NO_ACCESS_WAKE	8		/* T if no wake when n_accesses goes 0 */
#define FSCACHE_COOKIE_DO_RELINQUISH	9		/* T if this cookie needs relinquishment */
#define FSCACHE_COOKIE_DO_WITHDRAW	10		/* T if this cookie needs withdrawing */
#define FSCACHE_COOKIE_DO_LRU_DISCARD	11		/* T if this cookie needs LRU discard */
#define FSCACHE_COOKIE_DO_PREP_TO_WRITE	12		/* T if cookie needs write preparation */
#define FSCACHE_COOKIE_HAVE_DATA	13		/* T if this cookie has data stored */
#define FSCACHE_COOKIE_IS_HASHED	14		/* T if this cookie is hashed */
#define FSCACHE_COOKIE_DO_INVALIDATE	15		/* T if cookie needs invalidation */

	enum fscache_cookie_state	state;
	u8				advice;		/* FSCACHE_ADV_* */
	u8				key_len;	/* Length of index key */
	u8				aux_len;	/* Length of auxiliary data */
	u32				key_hash;	/* Hash of volume, key, len */
	union {
		void			*key;		/* Index key */
		u8			inline_key[16];	/* - If the key is short enough */
	};
	union {
		void			*aux;		/* Auxiliary data */
		u8			inline_aux[8];	/* - If the aux data is short enough */
	};
};

/*
 * slow-path functions for when there is actually caching available, and the
 * netfs does actually have a valid token
 * - these are not to be called directly
 * - these are undefined symbols when FS-Cache is not configured and the
 *   optimiser takes care of not using them
 */
extern struct fscache_volume *__fscache_acquire_volume(const char *, const char *,
						       const void *, size_t);
extern void __fscache_relinquish_volume(struct fscache_volume *, const void *, bool);

extern struct fscache_cookie *__fscache_acquire_cookie(
	struct fscache_volume *,
	u8,
	const void *, size_t,
	const void *, size_t,
	loff_t);
extern void __fscache_use_cookie(struct fscache_cookie *, bool);
extern void __fscache_unuse_cookie(struct fscache_cookie *, const void *, const loff_t *);
extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool);
extern void __fscache_resize_cookie(struct fscache_cookie *, loff_t);
extern void __fscache_invalidate(struct fscache_cookie *, const void *, loff_t, unsigned int);
extern int __fscache_begin_read_operation(struct netfs_cache_resources *, struct fscache_cookie *);
extern int __fscache_begin_write_operation(struct netfs_cache_resources *, struct fscache_cookie *);

extern void __fscache_write_to_cache(struct fscache_cookie *, struct address_space *,
				     loff_t, size_t, loff_t, netfs_io_terminated_t, void *,
				     bool);
extern void __fscache_clear_page_bits(struct address_space *, loff_t, size_t);

/**
 * fscache_acquire_volume - Register a volume as desiring caching services
 * @volume_key: An identification string for the volume
 * @cache_name: The name of the cache to use (or NULL for the default)
 * @coherency_data: Piece of arbitrary coherency data to check (or NULL)
 * @coherency_len: The size of the coherency data
 *
 * Register a volume as desiring caching services if they're available.  The
 * caller must provide an identifier for the volume and may also indicate which
 * cache it should be in.  If a preexisting volume entry is found in the cache,
 * the coherency data must match otherwise the entry will be invalidated.
 *
 * Returns a cookie pointer on success, -ENOMEM if out of memory or -EBUSY if a
 * cache volume of that name is already acquired.  Note that "NULL" is a valid
 * cookie pointer and can be returned if caching is refused.
 */
static inline
struct fscache_volume *fscache_acquire_volume(const char *volume_key,
					      const char *cache_name,
					      const void *coherency_data,
					      size_t coherency_len)
{
	if (!fscache_available())
		return NULL;
	return __fscache_acquire_volume(volume_key, cache_name,
					coherency_data, coherency_len);
}

/**
 * fscache_relinquish_volume - Cease caching a volume
 * @volume: The volume cookie
 * @coherency_data: Piece of arbitrary coherency data to set (or NULL)
 * @invalidate: True if the volume should be invalidated
 *
 * Indicate that a filesystem no longer desires caching services for a volume.
 * The caller must have relinquished all file cookies prior to calling this.
 * The stored coherency data is updated.
 */
static inline
void fscache_relinquish_volume(struct fscache_volume *volume,
			       const void *coherency_data,
			       bool invalidate)
{
	if (fscache_volume_valid(volume))
		__fscache_relinquish_volume(volume, coherency_data, invalidate);
}

/**
 * fscache_acquire_cookie - Acquire a cookie to represent a cache object
 * @volume: The volume in which to locate/create this cookie
 * @advice: Advice flags (FSCACHE_COOKIE_ADV_*)
 * @index_key: The index key for this cookie
 * @index_key_len: Size of the index key
 * @aux_data: The auxiliary data for the cookie (may be NULL)
 * @aux_data_len: Size of the auxiliary data buffer
 * @object_size: The initial size of object
 *
 * Acquire a cookie to represent a data file within the given cache volume.
 *
 * See Documentation/filesystems/caching/netfs-api.rst for a complete
 * description.
 */
static inline
struct fscache_cookie *fscache_acquire_cookie(struct fscache_volume *volume,
					      u8 advice,
					      const void *index_key,
					      size_t index_key_len,
					      const void *aux_data,
					      size_t aux_data_len,
					      loff_t object_size)
{
	if (!fscache_volume_valid(volume))
		return NULL;
	return __fscache_acquire_cookie(volume, advice,
					index_key, index_key_len,
					aux_data, aux_data_len,
					object_size);
}

/**
 * fscache_use_cookie - Request usage of cookie attached to an object
 * @cookie: The cookie representing the cache object
 * @will_modify: If cache is expected to be modified locally
 *
 * Request usage of the cookie attached to an object.  The caller should tell
 * the cache if the object's contents are about to be modified locally and then
 * the cache can apply the policy that has been set to handle this case.
 */
static inline void fscache_use_cookie(struct fscache_cookie *cookie,
				      bool will_modify)
{
	if (fscache_cookie_valid(cookie))
		__fscache_use_cookie(cookie, will_modify);
}

/**
 * fscache_unuse_cookie - Cease usage of cookie attached to an object
 * @cookie: The cookie representing the cache object
 * @aux_data: Updated auxiliary data (or NULL)
 * @object_size: Revised size of the object (or NULL)
 *
 * Cease usage of the cookie attached to an object.  When the users count
 * reaches zero then the cookie relinquishment will be permitted to proceed.
 */
static inline void fscache_unuse_cookie(struct fscache_cookie *cookie,
					const void *aux_data,
					const loff_t *object_size)
{
	if (fscache_cookie_valid(cookie))
		__fscache_unuse_cookie(cookie, aux_data, object_size);
}

/**
 * fscache_relinquish_cookie - Return the cookie to the cache, maybe discarding
 * it
 * @cookie: The cookie being returned
 * @retire: True if the cache object the cookie represents is to be discarded
 *
 * This function returns a cookie to the cache, forcibly discarding the
 * associated cache object if retire is set to true.
 *
 * See Documentation/filesystems/caching/netfs-api.rst for a complete
 * description.
 */
static inline
void fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire)
{
	if (fscache_cookie_valid(cookie))
		__fscache_relinquish_cookie(cookie, retire);
}

/*
 * Find the auxiliary data on a cookie.
 */
static inline void *fscache_get_aux(struct fscache_cookie *cookie)
{
	if (cookie->aux_len <= sizeof(cookie->inline_aux))
		return cookie->inline_aux;
	else
		return cookie->aux;
}

/*
 * Update the auxiliary data on a cookie.
 */
static inline
void fscache_update_aux(struct fscache_cookie *cookie,
			const void *aux_data, const loff_t *object_size)
{
	void *p = fscache_get_aux(cookie);

	if (aux_data && p)
		memcpy(p, aux_data, cookie->aux_len);
	if (object_size)
		cookie->object_size = *object_size;
}

#ifdef CONFIG_FSCACHE_STATS
extern atomic_t fscache_n_updates;
#endif

static inline
void __fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data,
			     const loff_t *object_size)
{
#ifdef CONFIG_FSCACHE_STATS
	atomic_inc(&fscache_n_updates);
#endif
	fscache_update_aux(cookie, aux_data, object_size);
	smp_wmb();
	set_bit(FSCACHE_COOKIE_NEEDS_UPDATE, &cookie->flags);
}

/**
 * fscache_update_cookie - Request that a cache object be updated
 * @cookie: The cookie representing the cache object
 * @aux_data: The updated auxiliary data for the cookie (may be NULL)
 * @object_size: The current size of the object (may be NULL)
 *
 * Request an update of the index data for the cache object associated with the
 * cookie.  The auxiliary data on the cookie will be updated first if @aux_data
 * is set and the object size will be updated and the object possibly trimmed
 * if @object_size is set.
 *
 * See Documentation/filesystems/caching/netfs-api.rst for a complete
 * description.
 */
static inline
void fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data,
			   const loff_t *object_size)
{
	if (fscache_cookie_enabled(cookie))
		__fscache_update_cookie(cookie, aux_data, object_size);
}

/**
 * fscache_resize_cookie - Request that a cache object be resized
 * @cookie: The cookie representing the cache object
 * @new_size: The new size of the object (may be NULL)
 *
 * Request that the size of an object be changed.
 *
 * See Documentation/filesystems/caching/netfs-api.rst for a complete
 * description.
 */
static inline
void fscache_resize_cookie(struct fscache_cookie *cookie, loff_t new_size)
{
	if (fscache_cookie_enabled(cookie))
		__fscache_resize_cookie(cookie, new_size);
}

/**
 * fscache_invalidate - Notify cache that an object needs invalidation
 * @cookie: The cookie representing the cache object
 * @aux_data: The updated auxiliary data for the cookie (may be NULL)
 * @size: The revised size of the object.
 * @flags: Invalidation flags (FSCACHE_INVAL_*)
 *
 * Notify the cache that an object is needs to be invalidated and that it
 * should abort any retrievals or stores it is doing on the cache.  This
 * increments inval_counter on the cookie which can be used by the caller to
 * reconsider I/O requests as they complete.
 *
 * If @flags has FSCACHE_INVAL_DIO_WRITE set, this indicates that this is due
 * to a direct I/O write and will cause caching to be disabled on this cookie
 * until it is completely unused.
 *
 * See Documentation/filesystems/caching/netfs-api.rst for a complete
 * description.
 */
static inline
void fscache_invalidate(struct fscache_cookie *cookie,
			const void *aux_data, loff_t size, unsigned int flags)
{
	if (fscache_cookie_enabled(cookie))
		__fscache_invalidate(cookie, aux_data, size, flags);
}

/**
 * fscache_operation_valid - Return true if operations resources are usable
 * @cres: The resources to check.
 *
 * Returns a pointer to the operations table if usable or NULL if not.
 */
static inline
const struct netfs_cache_ops *fscache_operation_valid(const struct netfs_cache_resources *cres)
{
	return fscache_resources_valid(cres) ? cres->ops : NULL;
}

/**
 * fscache_begin_read_operation - Begin a read operation for the netfs lib
 * @cres: The cache resources for the read being performed
 * @cookie: The cookie representing the cache object
 *
 * Begin a read operation on behalf of the netfs helper library.  @cres
 * indicates the cache resources to which the operation state should be
 * attached; @cookie indicates the cache object that will be accessed.
 *
 * @cres->inval_counter is set from @cookie->inval_counter for comparison at
 * the end of the operation.  This allows invalidation during the operation to
 * be detected by the caller.
 *
 * Returns:
 * * 0		- Success
 * * -ENOBUFS	- No caching available
 * * Other error code from the cache, such as -ENOMEM.
 */
static inline
int fscache_begin_read_operation(struct netfs_cache_resources *cres,
				 struct fscache_cookie *cookie)
{
	if (fscache_cookie_enabled(cookie))
		return __fscache_begin_read_operation(cres, cookie);
	return -ENOBUFS;
}

/**
 * fscache_end_operation - End the read operation for the netfs lib
 * @cres: The cache resources for the read operation
 *
 * Clean up the resources at the end of the read request.
 */
static inline void fscache_end_operation(struct netfs_cache_resources *cres)
{
	const struct netfs_cache_ops *ops = fscache_operation_valid(cres);

	if (ops)
		ops->end_operation(cres);
}

/**
 * fscache_read - Start a read from the cache.
 * @cres: The cache resources to use
 * @start_pos: The beginning file offset in the cache file
 * @iter: The buffer to fill - and also the length
 * @read_hole: How to handle a hole in the data.
 * @term_func: The function to call upon completion
 * @term_func_priv: The private data for @term_func
 *
 * Start a read from the cache.  @cres indicates the cache object to read from
 * and must be obtained by a call to fscache_begin_operation() beforehand.
 *
 * The data is read into the iterator, @iter, and that also indicates the size
 * of the operation.  @start_pos is the start position in the file, though if
 * @seek_data is set appropriately, the cache can use SEEK_DATA to find the
 * next piece of data, writing zeros for the hole into the iterator.
 *
 * Upon termination of the operation, @term_func will be called and supplied
 * with @term_func_priv plus the amount of data written, if successful, or the
 * error code otherwise.
 *
 * @read_hole indicates how a partially populated region in the cache should be
 * handled.  It can be one of a number of settings:
 *
 *	NETFS_READ_HOLE_IGNORE - Just try to read (may return a short read).
 *
 *	NETFS_READ_HOLE_CLEAR - Seek for data, clearing the part of the buffer
 *				skipped over, then do as for IGNORE.
 *
 *	NETFS_READ_HOLE_FAIL - Give ENODATA if we encounter a hole.
 */
static inline
int fscache_read(struct netfs_cache_resources *cres,
		 loff_t start_pos,
		 struct iov_iter *iter,
		 enum netfs_read_from_hole read_hole,
		 netfs_io_terminated_t term_func,
		 void *term_func_priv)
{
	const struct netfs_cache_ops *ops = fscache_operation_valid(cres);
	return ops->read(cres, start_pos, iter, read_hole,
			 term_func, term_func_priv);
}

/**
 * fscache_begin_write_operation - Begin a write operation for the netfs lib
 * @cres: The cache resources for the write being performed
 * @cookie: The cookie representing the cache object
 *
 * Begin a write operation on behalf of the netfs helper library.  @cres
 * indicates the cache resources to which the operation state should be
 * attached; @cookie indicates the cache object that will be accessed.
 *
 * @cres->inval_counter is set from @cookie->inval_counter for comparison at
 * the end of the operation.  This allows invalidation during the operation to
 * be detected by the caller.
 *
 * Returns:
 * * 0		- Success
 * * -ENOBUFS	- No caching available
 * * Other error code from the cache, such as -ENOMEM.
 */
static inline
int fscache_begin_write_operation(struct netfs_cache_resources *cres,
				  struct fscache_cookie *cookie)
{
	if (fscache_cookie_enabled(cookie))
		return __fscache_begin_write_operation(cres, cookie);
	return -ENOBUFS;
}

/**
 * fscache_write - Start a write to the cache.
 * @cres: The cache resources to use
 * @start_pos: The beginning file offset in the cache file
 * @iter: The data to write - and also the length
 * @term_func: The function to call upon completion
 * @term_func_priv: The private data for @term_func
 *
 * Start a write to the cache.  @cres indicates the cache object to write to and
 * must be obtained by a call to fscache_begin_operation() beforehand.
 *
 * The data to be written is obtained from the iterator, @iter, and that also
 * indicates the size of the operation.  @start_pos is the start position in
 * the file.
 *
 * Upon termination of the operation, @term_func will be called and supplied
 * with @term_func_priv plus the amount of data written, if successful, or the
 * error code otherwise.
 */
static inline
int fscache_write(struct netfs_cache_resources *cres,
		  loff_t start_pos,
		  struct iov_iter *iter,
		  netfs_io_terminated_t term_func,
		  void *term_func_priv)
{
	const struct netfs_cache_ops *ops = fscache_operation_valid(cres);
	return ops->write(cres, start_pos, iter, term_func, term_func_priv);
}

/**
 * fscache_clear_page_bits - Clear the PG_fscache bits from a set of pages
 * @mapping: The netfs inode to use as the source
 * @start: The start position in @mapping
 * @len: The amount of data to unlock
 * @caching: If PG_fscache has been set
 *
 * Clear the PG_fscache flag from a sequence of pages and wake up anyone who's
 * waiting.
 */
static inline void fscache_clear_page_bits(struct address_space *mapping,
					   loff_t start, size_t len,
					   bool caching)
{
	if (caching)
		__fscache_clear_page_bits(mapping, start, len);
}

/**
 * fscache_write_to_cache - Save a write to the cache and clear PG_fscache
 * @cookie: The cookie representing the cache object
 * @mapping: The netfs inode to use as the source
 * @start: The start position in @mapping
 * @len: The amount of data to write back
 * @i_size: The new size of the inode
 * @term_func: The function to call upon completion
 * @term_func_priv: The private data for @term_func
 * @caching: If PG_fscache has been set
 *
 * Helper function for a netfs to write dirty data from an inode into the cache
 * object that's backing it.
 *
 * @start and @len describe the range of the data.  This does not need to be
 * page-aligned, but to satisfy DIO requirements, the cache may expand it up to
 * the page boundaries on either end.  All the pages covering the range must be
 * marked with PG_fscache.
 *
 * If given, @term_func will be called upon completion and supplied with
 * @term_func_priv.  Note that the PG_fscache flags will have been cleared by
 * this point, so the netfs must retain its own pin on the mapping.
 */
static inline void fscache_write_to_cache(struct fscache_cookie *cookie,
					  struct address_space *mapping,
					  loff_t start, size_t len, loff_t i_size,
					  netfs_io_terminated_t term_func,
					  void *term_func_priv,
					  bool caching)
{
	if (caching)
		__fscache_write_to_cache(cookie, mapping, start, len, i_size,
					 term_func, term_func_priv, caching);
	else if (term_func)
		term_func(term_func_priv, -ENOBUFS, false);

}

/**
 * fscache_note_page_release - Note that a netfs page got released
 * @cookie: The cookie corresponding to the file
 *
 * Note that a page that has been copied to the cache has been released.  This
 * means that future reads will need to look in the cache to see if it's there.
 */
static inline
void fscache_note_page_release(struct fscache_cookie *cookie)
{
	/* If we've written data to the cache (HAVE_DATA) and there wasn't any
	 * data in the cache when we started (NO_DATA_TO_READ), it may no
	 * longer be true that we can skip reading from the cache - so clear
	 * the flag that causes reads to be skipped.
	 */
	if (cookie &&
	    test_bit(FSCACHE_COOKIE_HAVE_DATA, &cookie->flags) &&
	    test_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags))
		clear_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags);
}

#endif /* _LINUX_FSCACHE_H */
¿Qué es la limpieza dental de perros? - Clínica veterinaria


Es la eliminación del sarro y la placa adherida a la superficie de los dientes mediante un equipo de ultrasonidos que garantiza la integridad de las piezas dentales a la vez que elimina en profundidad cualquier resto de suciedad.

A continuación se procede al pulido de los dientes mediante una fresa especial que elimina la placa bacteriana y devuelve a los dientes el aspecto sano que deben tener.

Una vez terminado todo el proceso, se mantiene al perro en observación hasta que se despierta de la anestesia, bajo la atenta supervisión de un veterinario.

¿Cada cuánto tiempo tengo que hacerle una limpieza dental a mi perro?

A partir de cierta edad, los perros pueden necesitar una limpieza dental anual o bianual. Depende de cada caso. En líneas generales, puede decirse que los perros de razas pequeñas suelen acumular más sarro y suelen necesitar una atención mayor en cuanto a higiene dental.


Riesgos de una mala higiene


Los riesgos más evidentes de una mala higiene dental en los perros son los siguientes:

  • Cuando la acumulación de sarro no se trata, se puede producir una inflamación y retracción de las encías que puede descalzar el diente y provocar caídas.
  • Mal aliento (halitosis).
  • Sarro perros
  • Puede ir a más
  • Las bacterias de la placa pueden trasladarse a través del torrente circulatorio a órganos vitales como el corazón ocasionando problemas de endocarditis en las válvulas. Las bacterias pueden incluso acantonarse en huesos (La osteomielitis es la infección ósea, tanto cortical como medular) provocando mucho dolor y una artritis séptica).

¿Cómo se forma el sarro?

El sarro es la calcificación de la placa dental. Los restos de alimentos, junto con las bacterias presentes en la boca, van a formar la placa bacteriana o placa dental. Si la placa no se retira, al mezclarse con la saliva y los minerales presentes en ella, reaccionará formando una costra. La placa se calcifica y se forma el sarro.

El sarro, cuando se forma, es de color blanquecino pero a medida que pasa el tiempo se va poniendo amarillo y luego marrón.

Síntomas de una pobre higiene dental
La señal más obvia de una mala salud dental canina es el mal aliento.

Sin embargo, a veces no es tan fácil de detectar
Y hay perros que no se dejan abrir la boca por su dueño. Por ejemplo…

Recientemente nos trajeron a la clínica a un perro que parpadeaba de un ojo y decía su dueño que le picaba un lado de la cara. Tenía molestias y dificultad para comer, lo que había llevado a sus dueños a comprarle comida blanda (que suele ser un poco más cara y llevar más contenido en grasa) durante medio año. Después de una exploración oftalmológica, nos dimos cuenta de que el ojo tenía una úlcera en la córnea probablemente de rascarse . Además, el canto lateral del ojo estaba inflamado. Tenía lo que en humanos llamamos flemón pero como era un perro de pelo largo, no se le notaba a simple vista. Al abrirle la boca nos llamó la atención el ver una muela llena de sarro. Le realizamos una radiografía y encontramos una fístula que llegaba hasta la parte inferior del ojo.

Le tuvimos que extraer la muela. Tras esto, el ojo se curó completamente con unos colirios y una lentilla protectora de úlcera. Afortunadamente, la úlcera no profundizó y no perforó el ojo. Ahora el perro come perfectamente a pesar de haber perdido una muela.

¿Cómo mantener la higiene dental de tu perro?
Hay varias maneras de prevenir problemas derivados de la salud dental de tu perro.

Limpiezas de dientes en casa
Es recomendable limpiar los dientes de tu perro semanal o diariamente si se puede. Existe una gran variedad de productos que se pueden utilizar:

Pastas de dientes.
Cepillos de dientes o dedales para el dedo índice, que hacen más fácil la limpieza.
Colutorios para echar en agua de bebida o directamente sobre el diente en líquido o en spray.

En la Clínica Tus Veterinarios enseñamos a nuestros clientes a tomar el hábito de limpiar los dientes de sus perros desde que son cachorros. Esto responde a nuestro compromiso con la prevención de enfermedades caninas.

Hoy en día tenemos muchos clientes que limpian los dientes todos los días a su mascota, y como resultado, se ahorran el dinero de hacer limpiezas dentales profesionales y consiguen una mejor salud de su perro.


Limpiezas dentales profesionales de perros y gatos

Recomendamos hacer una limpieza dental especializada anualmente. La realizamos con un aparato de ultrasonidos que utiliza agua para quitar el sarro. Después, procedemos a pulir los dientes con un cepillo de alta velocidad y una pasta especial. Hacemos esto para proteger el esmalte.

La frecuencia de limpiezas dentales necesaria varía mucho entre razas. En general, las razas grandes tienen buena calidad de esmalte, por lo que no necesitan hacerlo tan a menudo e incluso pueden pasarse la vida sin requerir una limpieza. Sin embargo, razas pequeñas como el Yorkshire o el Maltés, deben hacérselas todos los años desde cachorros si se quiere conservar sus piezas dentales.

Otro factor fundamental es la calidad del pienso. Algunas marcas han diseñado croquetas que limpian la superficie del diente y de la muela al masticarse.

Ultrasonido para perros

¿Se necesita anestesia para las limpiezas dentales de perros y gatos?

La limpieza dental en perros no es una técnica que pueda practicarse sin anestesia general , aunque hay veces que los propietarios no quieren anestesiar y si tiene poco sarro y el perro es muy bueno se puede intentar…… , pero no se va a poder pulir ni acceder a todas la zona de la boca …. Además los limpiadores dentales van a irrigar agua y hay riesgo de aspiración a vías respiratorias si no se realiza una anestesia correcta con intubación traqueal . En resumen , sin anestesia no se va hacer una correcta limpieza dental.

Tampoco sirve la sedación ya que necesitamos que el animal esté totalmente quieto, y el veterinario tenga un acceso completo a todas sus piezas dentales y encías.

Alimentos para la limpieza dental

Hay que tener cierto cuidado a la hora de comprar determinados alimentos porque no todos son saludables. Algunos tienen demasiado contenido graso, que en exceso puede causar problemas cardiovasculares y obesidad.

Los mejores alimentos para los dientes son aquellos que están elaborados por empresas farmacéuticas y llevan componentes químicos con tratamientos específicos para el diente del perro. Esto implica no solo limpieza a través de la acción mecánica de morder sino también un tratamiento antibacteriano para prevenir el sarro.

Conclusión

Si eres como la mayoría de dueños, por falta de tiempo , es probable que no estés prestando la suficiente atención a la limpieza dental de tu perro. Por eso te animamos a que comiences a limpiar los dientes de tu perro y consideres atender a su higiene bucal con frecuencia.

Estas simples medidas pueden conllevar a que tu perro tenga una vida más larga y mucho más saludable.

Si te resulta imposible introducir un cepillo de dientes a tu perro en la boca, pásate con él por clínica Tus Veterinarios y te explicamos cómo hacerlo.

Necesitas hacer una limpieza dental profesional a tu mascota?
Llámanos al 622575274 o contacta con nosotros

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

¡Hola!