Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull VFS update from Al Viro: "fscache fixes, ESTALE patchset, vmtruncate removal series, assorted misc stuff." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (79 commits) vfs: make lremovexattr retry once on ESTALE error vfs: make removexattr retry once on ESTALE vfs: make llistxattr retry once on ESTALE error vfs: make listxattr retry once on ESTALE error vfs: make lgetxattr retry once on ESTALE vfs: make getxattr retry once on an ESTALE error vfs: allow lsetxattr() to retry once on ESTALE errors vfs: allow setxattr to retry once on ESTALE errors vfs: allow utimensat() calls to retry once on an ESTALE error vfs: fix user_statfs to retry once on ESTALE errors vfs: make fchownat retry once on ESTALE errors vfs: make fchmodat retry once on ESTALE errors vfs: have chroot retry once on ESTALE error vfs: have chdir retry lookup and call once on ESTALE error vfs: have faccessat retry once on an ESTALE error vfs: have do_sys_truncate retry once on an ESTALE error vfs: fix renameat to retry on ESTALE errors vfs: make do_unlinkat retry once on ESTALE errors vfs: make do_rmdir retry once on ESTALE errors vfs: add a flags argument to user_path_parent ...
This commit is contained in:
@@ -202,7 +202,6 @@ struct dentry_operations {
|
||||
#define DCACHE_MOUNTED 0x10000 /* is a mountpoint */
|
||||
#define DCACHE_NEED_AUTOMOUNT 0x20000 /* handle automount on this dir */
|
||||
#define DCACHE_MANAGE_TRANSIT 0x40000 /* manage transit from this dirent */
|
||||
#define DCACHE_NEED_LOOKUP 0x80000 /* dentry requires i_op->lookup */
|
||||
#define DCACHE_MANAGED_DENTRY \
|
||||
(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
|
||||
|
||||
@@ -408,13 +407,6 @@ static inline bool d_mountpoint(struct dentry *dentry)
|
||||
return dentry->d_flags & DCACHE_MOUNTED;
|
||||
}
|
||||
|
||||
static inline bool d_need_lookup(struct dentry *dentry)
|
||||
{
|
||||
return dentry->d_flags & DCACHE_NEED_LOOKUP;
|
||||
}
|
||||
|
||||
extern void d_clear_need_lookup(struct dentry *dentry);
|
||||
|
||||
extern int sysctl_vfs_cache_pressure;
|
||||
|
||||
#endif /* __LINUX_DCACHE_H */
|
||||
|
||||
+1
-5
@@ -1445,10 +1445,6 @@ static inline void sb_start_intwrite(struct super_block *sb)
|
||||
|
||||
extern bool inode_owner_or_capable(const struct inode *inode);
|
||||
|
||||
/* not quite ready to be deprecated, but... */
|
||||
extern void lock_super(struct super_block *);
|
||||
extern void unlock_super(struct super_block *);
|
||||
|
||||
/*
|
||||
* VFS helper functions..
|
||||
*/
|
||||
@@ -1565,7 +1561,6 @@ struct inode_operations {
|
||||
int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
|
||||
int (*rename) (struct inode *, struct dentry *,
|
||||
struct inode *, struct dentry *);
|
||||
void (*truncate) (struct inode *);
|
||||
int (*setattr) (struct dentry *, struct iattr *);
|
||||
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
|
||||
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
|
||||
@@ -1999,6 +1994,7 @@ struct filename {
|
||||
bool separate; /* should "name" be freed? */
|
||||
};
|
||||
|
||||
extern long vfs_truncate(struct path *, loff_t);
|
||||
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
|
||||
struct file *filp);
|
||||
extern int do_fallocate(struct file *file, int mode, loff_t offset,
|
||||
|
||||
@@ -75,6 +75,16 @@ extern wait_queue_head_t fscache_cache_cleared_wq;
|
||||
typedef void (*fscache_operation_release_t)(struct fscache_operation *op);
|
||||
typedef void (*fscache_operation_processor_t)(struct fscache_operation *op);
|
||||
|
||||
enum fscache_operation_state {
|
||||
FSCACHE_OP_ST_BLANK, /* Op is not yet submitted */
|
||||
FSCACHE_OP_ST_INITIALISED, /* Op is initialised */
|
||||
FSCACHE_OP_ST_PENDING, /* Op is blocked from running */
|
||||
FSCACHE_OP_ST_IN_PROGRESS, /* Op is in progress */
|
||||
FSCACHE_OP_ST_COMPLETE, /* Op is complete */
|
||||
FSCACHE_OP_ST_CANCELLED, /* Op has been cancelled */
|
||||
FSCACHE_OP_ST_DEAD /* Op is now dead */
|
||||
};
|
||||
|
||||
struct fscache_operation {
|
||||
struct work_struct work; /* record for async ops */
|
||||
struct list_head pend_link; /* link in object->pending_ops */
|
||||
@@ -86,10 +96,10 @@ struct fscache_operation {
|
||||
#define FSCACHE_OP_MYTHREAD 0x0002 /* - processing is done be issuing thread, not pool */
|
||||
#define FSCACHE_OP_WAITING 4 /* cleared when op is woken */
|
||||
#define FSCACHE_OP_EXCLUSIVE 5 /* exclusive op, other ops must wait */
|
||||
#define FSCACHE_OP_DEAD 6 /* op is now dead */
|
||||
#define FSCACHE_OP_DEC_READ_CNT 7 /* decrement object->n_reads on destruction */
|
||||
#define FSCACHE_OP_KEEP_FLAGS 0xc0 /* flags to keep when repurposing an op */
|
||||
#define FSCACHE_OP_DEC_READ_CNT 6 /* decrement object->n_reads on destruction */
|
||||
#define FSCACHE_OP_KEEP_FLAGS 0x0070 /* flags to keep when repurposing an op */
|
||||
|
||||
enum fscache_operation_state state;
|
||||
atomic_t usage;
|
||||
unsigned debug_id; /* debugging ID */
|
||||
|
||||
@@ -106,6 +116,7 @@ extern atomic_t fscache_op_debug_id;
|
||||
extern void fscache_op_work_func(struct work_struct *work);
|
||||
|
||||
extern void fscache_enqueue_operation(struct fscache_operation *);
|
||||
extern void fscache_op_complete(struct fscache_operation *, bool);
|
||||
extern void fscache_put_operation(struct fscache_operation *);
|
||||
|
||||
/**
|
||||
@@ -122,6 +133,7 @@ static inline void fscache_operation_init(struct fscache_operation *op,
|
||||
{
|
||||
INIT_WORK(&op->work, fscache_op_work_func);
|
||||
atomic_set(&op->usage, 1);
|
||||
op->state = FSCACHE_OP_ST_INITIALISED;
|
||||
op->debug_id = atomic_inc_return(&fscache_op_debug_id);
|
||||
op->processor = processor;
|
||||
op->release = release;
|
||||
@@ -138,6 +150,7 @@ struct fscache_retrieval {
|
||||
void *context; /* netfs read context (pinned) */
|
||||
struct list_head to_do; /* list of things to be done by the backend */
|
||||
unsigned long start_time; /* time at which retrieval started */
|
||||
unsigned n_pages; /* number of pages to be retrieved */
|
||||
};
|
||||
|
||||
typedef int (*fscache_page_retrieval_func_t)(struct fscache_retrieval *op,
|
||||
@@ -173,9 +186,23 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op)
|
||||
fscache_enqueue_operation(&op->op);
|
||||
}
|
||||
|
||||
/**
|
||||
* fscache_retrieval_complete - Record (partial) completion of a retrieval
|
||||
* @op: The retrieval operation affected
|
||||
* @n_pages: The number of pages to account for
|
||||
*/
|
||||
static inline void fscache_retrieval_complete(struct fscache_retrieval *op,
|
||||
int n_pages)
|
||||
{
|
||||
op->n_pages -= n_pages;
|
||||
if (op->n_pages <= 0)
|
||||
fscache_op_complete(&op->op, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* fscache_put_retrieval - Drop a reference to a retrieval operation
|
||||
* @op: The retrieval operation affected
|
||||
* @n_pages: The number of pages to account for
|
||||
*
|
||||
* Drop a reference to a retrieval operation.
|
||||
*/
|
||||
@@ -227,6 +254,9 @@ struct fscache_cache_ops {
|
||||
/* store the updated auxiliary data on an object */
|
||||
void (*update_object)(struct fscache_object *object);
|
||||
|
||||
/* Invalidate an object */
|
||||
void (*invalidate_object)(struct fscache_operation *op);
|
||||
|
||||
/* discard the resources pinned by an object and effect retirement if
|
||||
* necessary */
|
||||
void (*drop_object)(struct fscache_object *object);
|
||||
@@ -301,10 +331,29 @@ struct fscache_cookie {
|
||||
#define FSCACHE_COOKIE_PENDING_FILL 3 /* T if pending initial fill on object */
|
||||
#define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */
|
||||
#define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */
|
||||
#define FSCACHE_COOKIE_WAITING_ON_READS 6 /* T if cookie is waiting on reads */
|
||||
#define FSCACHE_COOKIE_INVALIDATING 7 /* T if cookie is being invalidated */
|
||||
};
|
||||
|
||||
extern struct fscache_cookie fscache_fsdef_index;
|
||||
|
||||
/*
|
||||
* Event list for fscache_object::{event_mask,events}
|
||||
*/
|
||||
enum {
|
||||
FSCACHE_OBJECT_EV_REQUEUE, /* T if object should be requeued */
|
||||
FSCACHE_OBJECT_EV_UPDATE, /* T if object should be updated */
|
||||
FSCACHE_OBJECT_EV_INVALIDATE, /* T if cache requested object invalidation */
|
||||
FSCACHE_OBJECT_EV_CLEARED, /* T if accessors all gone */
|
||||
FSCACHE_OBJECT_EV_ERROR, /* T if fatal error occurred during processing */
|
||||
FSCACHE_OBJECT_EV_RELEASE, /* T if netfs requested object release */
|
||||
FSCACHE_OBJECT_EV_RETIRE, /* T if netfs requested object retirement */
|
||||
FSCACHE_OBJECT_EV_WITHDRAW, /* T if cache requested object withdrawal */
|
||||
NR_FSCACHE_OBJECT_EVENTS
|
||||
};
|
||||
|
||||
#define FSCACHE_OBJECT_EVENTS_MASK ((1UL << NR_FSCACHE_OBJECT_EVENTS) - 1)
|
||||
|
||||
/*
|
||||
* on-disk cache file or index handle
|
||||
*/
|
||||
@@ -317,6 +366,7 @@ struct fscache_object {
|
||||
/* active states */
|
||||
FSCACHE_OBJECT_AVAILABLE, /* cleaning up object after creation */
|
||||
FSCACHE_OBJECT_ACTIVE, /* object is usable */
|
||||
FSCACHE_OBJECT_INVALIDATING, /* object is invalidating */
|
||||
FSCACHE_OBJECT_UPDATING, /* object is updating */
|
||||
|
||||
/* terminal states */
|
||||
@@ -332,10 +382,10 @@ struct fscache_object {
|
||||
|
||||
int debug_id; /* debugging ID */
|
||||
int n_children; /* number of child objects */
|
||||
int n_ops; /* number of ops outstanding on object */
|
||||
int n_ops; /* number of extant ops on object */
|
||||
int n_obj_ops; /* number of object ops outstanding on object */
|
||||
int n_in_progress; /* number of ops in progress */
|
||||
int n_exclusive; /* number of exclusive ops queued */
|
||||
int n_exclusive; /* number of exclusive ops queued or in progress */
|
||||
atomic_t n_reads; /* number of read ops in progress */
|
||||
spinlock_t lock; /* state and operations lock */
|
||||
|
||||
@@ -343,14 +393,6 @@ struct fscache_object {
|
||||
unsigned long event_mask; /* events this object is interested in */
|
||||
unsigned long events; /* events to be processed by this object
|
||||
* (order is important - using fls) */
|
||||
#define FSCACHE_OBJECT_EV_REQUEUE 0 /* T if object should be requeued */
|
||||
#define FSCACHE_OBJECT_EV_UPDATE 1 /* T if object should be updated */
|
||||
#define FSCACHE_OBJECT_EV_CLEARED 2 /* T if accessors all gone */
|
||||
#define FSCACHE_OBJECT_EV_ERROR 3 /* T if fatal error occurred during processing */
|
||||
#define FSCACHE_OBJECT_EV_RELEASE 4 /* T if netfs requested object release */
|
||||
#define FSCACHE_OBJECT_EV_RETIRE 5 /* T if netfs requested object retirement */
|
||||
#define FSCACHE_OBJECT_EV_WITHDRAW 6 /* T if cache requested object withdrawal */
|
||||
#define FSCACHE_OBJECT_EVENTS_MASK 0x7f /* mask of all events*/
|
||||
|
||||
unsigned long flags;
|
||||
#define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */
|
||||
@@ -504,6 +546,9 @@ extern void fscache_withdraw_cache(struct fscache_cache *cache);
|
||||
|
||||
extern void fscache_io_error(struct fscache_cache *cache);
|
||||
|
||||
extern void fscache_mark_page_cached(struct fscache_retrieval *op,
|
||||
struct page *page);
|
||||
|
||||
extern void fscache_mark_pages_cached(struct fscache_retrieval *op,
|
||||
struct pagevec *pagevec);
|
||||
|
||||
|
||||
+44
-6
@@ -135,14 +135,14 @@ struct fscache_cookie_def {
|
||||
*/
|
||||
void (*put_context)(void *cookie_netfs_data, void *context);
|
||||
|
||||
/* indicate pages that now have cache metadata retained
|
||||
* - this function should mark the specified pages as now being cached
|
||||
* - the pages will have been marked with PG_fscache before this is
|
||||
/* indicate page that now have cache metadata retained
|
||||
* - this function should mark the specified page as now being cached
|
||||
* - the page will have been marked with PG_fscache before this is
|
||||
* called, so this is optional
|
||||
*/
|
||||
void (*mark_pages_cached)(void *cookie_netfs_data,
|
||||
struct address_space *mapping,
|
||||
struct pagevec *cached_pvec);
|
||||
void (*mark_page_cached)(void *cookie_netfs_data,
|
||||
struct address_space *mapping,
|
||||
struct page *page);
|
||||
|
||||
/* indicate the cookie is no longer cached
|
||||
* - this function is called when the backing store currently caching
|
||||
@@ -185,6 +185,8 @@ extern struct fscache_cookie *__fscache_acquire_cookie(
|
||||
extern void __fscache_relinquish_cookie(struct fscache_cookie *, int);
|
||||
extern void __fscache_update_cookie(struct fscache_cookie *);
|
||||
extern int __fscache_attr_changed(struct fscache_cookie *);
|
||||
extern void __fscache_invalidate(struct fscache_cookie *);
|
||||
extern void __fscache_wait_on_invalidate(struct fscache_cookie *);
|
||||
extern int __fscache_read_or_alloc_page(struct fscache_cookie *,
|
||||
struct page *,
|
||||
fscache_rw_complete_t,
|
||||
@@ -389,6 +391,42 @@ int fscache_attr_changed(struct fscache_cookie *cookie)
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
/**
|
||||
* fscache_invalidate - Notify cache that an object needs invalidation
|
||||
* @cookie: The cookie representing the cache object
|
||||
*
|
||||
* 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. The object
|
||||
* is then marked non-caching until such time as the invalidation is complete.
|
||||
*
|
||||
* This can be called with spinlocks held.
|
||||
*
|
||||
* See Documentation/filesystems/caching/netfs-api.txt for a complete
|
||||
* description.
|
||||
*/
|
||||
static inline
|
||||
void fscache_invalidate(struct fscache_cookie *cookie)
|
||||
{
|
||||
if (fscache_cookie_valid(cookie))
|
||||
__fscache_invalidate(cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* fscache_wait_on_invalidate - Wait for invalidation to complete
|
||||
* @cookie: The cookie representing the cache object
|
||||
*
|
||||
* Wait for the invalidation of an object to complete.
|
||||
*
|
||||
* See Documentation/filesystems/caching/netfs-api.txt for a complete
|
||||
* description.
|
||||
*/
|
||||
static inline
|
||||
void fscache_wait_on_invalidate(struct fscache_cookie *cookie)
|
||||
{
|
||||
if (fscache_cookie_valid(cookie))
|
||||
__fscache_wait_on_invalidate(cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* fscache_reserve_space - Reserve data space for a cached object
|
||||
* @cookie: The cookie representing the cache object
|
||||
|
||||
@@ -1007,7 +1007,6 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
|
||||
|
||||
extern void truncate_pagecache(struct inode *inode, loff_t old, loff_t new);
|
||||
extern void truncate_setsize(struct inode *inode, loff_t newsize);
|
||||
extern int vmtruncate(struct inode *inode, loff_t offset);
|
||||
void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end);
|
||||
int truncate_inode_page(struct address_space *mapping, struct page *page);
|
||||
int generic_error_remove_page(struct address_space *mapping, struct page *page);
|
||||
|
||||
+18
-2
@@ -65,8 +65,8 @@ extern int user_path_at_empty(int, const char __user *, unsigned, struct path *,
|
||||
|
||||
extern int kern_path(const char *, unsigned, struct path *);
|
||||
|
||||
extern struct dentry *kern_path_create(int, const char *, struct path *, int);
|
||||
extern struct dentry *user_path_create(int, const char __user *, struct path *, int);
|
||||
extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int);
|
||||
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
|
||||
extern void done_path_create(struct path *, struct dentry *);
|
||||
extern struct dentry *kern_path_locked(const char *, struct path *);
|
||||
extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
|
||||
@@ -98,4 +98,20 @@ static inline void nd_terminate_link(void *name, size_t len, size_t maxlen)
|
||||
((char *) name)[min(len, maxlen)] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* retry_estale - determine whether the caller should retry an operation
|
||||
* @error: the error that would currently be returned
|
||||
* @flags: flags being used for next lookup attempt
|
||||
*
|
||||
* Check to see if the error code was -ESTALE, and then determine whether
|
||||
* to retry the call based on whether "flags" already has LOOKUP_REVAL set.
|
||||
*
|
||||
* Returns true if the caller should try the operation again.
|
||||
*/
|
||||
static inline bool
|
||||
retry_estale(const long error, const unsigned int flags)
|
||||
{
|
||||
return error == -ESTALE && !(flags & LOOKUP_REVAL);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_NAMEI_H */
|
||||
|
||||
Reference in New Issue
Block a user