Commit 88238805 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-5.2-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux

Pull orangefs updates from Mike Marshall:
 "This includes one fix and our "Orangefs through the pagecache" patch
  series which greatly improves our small IO performance and helps us
  pass more xfstests than before.

  Fix:
   - orangefs: truncate before updating size

  Pagecache series:
   - all the rest"

* tag 'for-linus-5.2-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux: (23 commits)
  orangefs: truncate before updating size
  orangefs: copy Orangefs-sized blocks into the pagecache if possible.
  orangefs: pass slot index back to readpage.
  orangefs: remember count when reading.
  orangefs: add orangefs_revalidate_mapping
  orangefs: implement writepages
  orangefs: write range tracking
  orangefs: avoid fsync service operation on flush
  orangefs: skip inode writeout if nothing to write
  orangefs: move do_readv_writev to direct_IO
  orangefs: do not return successful read when the client-core disappeared
  orangefs: implement writepage
  orangefs: migrate to generic_file_read_iter
  orangefs: service ops done for writeback are not killable
  orangefs: remove orangefs_readpages
  orangefs: reorganize setattr functions to track attribute changes
  orangefs: let setattr write to cached inode
  orangefs: set up and use backing_dev_info
  orangefs: hold i_lock during inode_getattr
  orangefs: update attributes rather than relying on server
  ...
parents dce45af5 33713cd0
...@@ -142,7 +142,7 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) ...@@ -142,7 +142,7 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
rc = __orangefs_set_acl(inode, acl, type); rc = __orangefs_set_acl(inode, acl, type);
} else { } else {
iattr.ia_valid = ATTR_MODE; iattr.ia_valid = ATTR_MODE;
rc = orangefs_inode_setattr(inode, &iattr); rc = __orangefs_setattr(inode, &iattr);
} }
return rc; return rc;
...@@ -185,7 +185,7 @@ int orangefs_init_acl(struct inode *inode, struct inode *dir) ...@@ -185,7 +185,7 @@ int orangefs_init_acl(struct inode *inode, struct inode *dir)
inode->i_mode = mode; inode->i_mode = mode;
iattr.ia_mode = mode; iattr.ia_mode = mode;
iattr.ia_valid |= ATTR_MODE; iattr.ia_valid |= ATTR_MODE;
orangefs_inode_setattr(inode, &iattr); __orangefs_setattr(inode, &iattr);
} }
return error; return error;
......
This diff is collapsed.
This diff is collapsed.
...@@ -76,19 +76,16 @@ static int orangefs_create(struct inode *dir, ...@@ -76,19 +76,16 @@ static int orangefs_create(struct inode *dir,
d_instantiate_new(dentry, inode); d_instantiate_new(dentry, inode);
orangefs_set_timeout(dentry); orangefs_set_timeout(dentry);
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
gossip_debug(GOSSIP_NAME_DEBUG, gossip_debug(GOSSIP_NAME_DEBUG,
"%s: dentry instantiated for %pd\n", "%s: dentry instantiated for %pd\n",
__func__, __func__,
dentry); dentry);
dir->i_mtime = dir->i_ctime = current_time(dir);
memset(&iattr, 0, sizeof iattr); memset(&iattr, 0, sizeof iattr);
iattr.ia_valid |= ATTR_MTIME; iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
orangefs_inode_setattr(dir, &iattr); iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
mark_inode_dirty_sync(dir); __orangefs_setattr(dir, &iattr);
ret = 0; ret = 0;
out: out:
op_release(new_op); op_release(new_op);
...@@ -210,11 +207,10 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -210,11 +207,10 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
if (!ret) { if (!ret) {
drop_nlink(inode); drop_nlink(inode);
dir->i_mtime = dir->i_ctime = current_time(dir);
memset(&iattr, 0, sizeof iattr); memset(&iattr, 0, sizeof iattr);
iattr.ia_valid |= ATTR_MTIME; iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
orangefs_inode_setattr(dir, &iattr); iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
mark_inode_dirty_sync(dir); __orangefs_setattr(dir, &iattr);
} }
return ret; return ret;
} }
...@@ -291,19 +287,16 @@ static int orangefs_symlink(struct inode *dir, ...@@ -291,19 +287,16 @@ static int orangefs_symlink(struct inode *dir,
d_instantiate_new(dentry, inode); d_instantiate_new(dentry, inode);
orangefs_set_timeout(dentry); orangefs_set_timeout(dentry);
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
gossip_debug(GOSSIP_NAME_DEBUG, gossip_debug(GOSSIP_NAME_DEBUG,
"Inode (Symlink) %pU -> %pd\n", "Inode (Symlink) %pU -> %pd\n",
get_khandle_from_ino(inode), get_khandle_from_ino(inode),
dentry); dentry);
dir->i_mtime = dir->i_ctime = current_time(dir);
memset(&iattr, 0, sizeof iattr); memset(&iattr, 0, sizeof iattr);
iattr.ia_valid |= ATTR_MTIME; iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
orangefs_inode_setattr(dir, &iattr); iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
mark_inode_dirty_sync(dir); __orangefs_setattr(dir, &iattr);
ret = 0; ret = 0;
out: out:
op_release(new_op); op_release(new_op);
...@@ -360,8 +353,6 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode ...@@ -360,8 +353,6 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
d_instantiate_new(dentry, inode); d_instantiate_new(dentry, inode);
orangefs_set_timeout(dentry); orangefs_set_timeout(dentry);
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
gossip_debug(GOSSIP_NAME_DEBUG, gossip_debug(GOSSIP_NAME_DEBUG,
"Inode (Directory) %pU -> %pd\n", "Inode (Directory) %pU -> %pd\n",
...@@ -372,11 +363,10 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode ...@@ -372,11 +363,10 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
* NOTE: we have no good way to keep nlink consistent for directories * NOTE: we have no good way to keep nlink consistent for directories
* across clients; keep constant at 1. * across clients; keep constant at 1.
*/ */
dir->i_mtime = dir->i_ctime = current_time(dir);
memset(&iattr, 0, sizeof iattr); memset(&iattr, 0, sizeof iattr);
iattr.ia_valid |= ATTR_MTIME; iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
orangefs_inode_setattr(dir, &iattr); iattr.ia_mtime = iattr.ia_ctime = current_time(dir);
mark_inode_dirty_sync(dir); __orangefs_setattr(dir, &iattr);
out: out:
op_release(new_op); op_release(new_op);
return ret; return ret;
...@@ -389,6 +379,7 @@ static int orangefs_rename(struct inode *old_dir, ...@@ -389,6 +379,7 @@ static int orangefs_rename(struct inode *old_dir,
unsigned int flags) unsigned int flags)
{ {
struct orangefs_kernel_op_s *new_op; struct orangefs_kernel_op_s *new_op;
struct iattr iattr;
int ret; int ret;
if (flags) if (flags)
...@@ -398,7 +389,10 @@ static int orangefs_rename(struct inode *old_dir, ...@@ -398,7 +389,10 @@ static int orangefs_rename(struct inode *old_dir,
"orangefs_rename: called (%pd2 => %pd2) ct=%d\n", "orangefs_rename: called (%pd2 => %pd2) ct=%d\n",
old_dentry, new_dentry, d_count(new_dentry)); old_dentry, new_dentry, d_count(new_dentry));
ORANGEFS_I(new_dentry->d_parent->d_inode)->getattr_time = jiffies - 1; memset(&iattr, 0, sizeof iattr);
iattr.ia_valid |= ATTR_MTIME | ATTR_CTIME;
iattr.ia_mtime = iattr.ia_ctime = current_time(new_dir);
__orangefs_setattr(new_dir, &iattr);
new_op = op_alloc(ORANGEFS_VFS_OP_RENAME); new_op = op_alloc(ORANGEFS_VFS_OP_RENAME);
if (!new_op) if (!new_op)
......
...@@ -538,3 +538,16 @@ int orangefs_bufmap_copy_to_iovec(struct iov_iter *iter, ...@@ -538,3 +538,16 @@ int orangefs_bufmap_copy_to_iovec(struct iov_iter *iter,
} }
return 0; return 0;
} }
void orangefs_bufmap_page_fill(void *page_to,
int buffer_index,
int slot_index)
{
struct orangefs_bufmap_desc *from;
void *page_from;
from = &__orangefs_bufmap->desc_array[buffer_index];
page_from = kmap_atomic(from->page_array[slot_index]);
memcpy(page_to, page_from, PAGE_SIZE);
kunmap_atomic(page_from);
}
...@@ -34,4 +34,6 @@ int orangefs_bufmap_copy_to_iovec(struct iov_iter *iter, ...@@ -34,4 +34,6 @@ int orangefs_bufmap_copy_to_iovec(struct iov_iter *iter,
int buffer_index, int buffer_index,
size_t size); size_t size);
void orangefs_bufmap_page_fill(void *kaddr, int buffer_index, int slot_index);
#endif /* __ORANGEFS_BUFMAP_H */ #endif /* __ORANGEFS_BUFMAP_H */
...@@ -963,7 +963,7 @@ int orangefs_debugfs_new_client_mask(void __user *arg) ...@@ -963,7 +963,7 @@ int orangefs_debugfs_new_client_mask(void __user *arg)
return ret; return ret;
} }
int orangefs_debugfs_new_client_string(void __user *arg) int orangefs_debugfs_new_client_string(void __user *arg)
{ {
int ret; int ret;
...@@ -1016,7 +1016,7 @@ int orangefs_debugfs_new_client_string(void __user *arg) ...@@ -1016,7 +1016,7 @@ int orangefs_debugfs_new_client_string(void __user *arg)
return 0; return 0;
} }
int orangefs_debugfs_new_debug(void __user *arg) int orangefs_debugfs_new_debug(void __user *arg)
{ {
struct dev_mask_info_s mask_info = {0}; struct dev_mask_info_s mask_info = {0};
int ret; int ret;
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include <linux/hashtable.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -192,7 +193,13 @@ struct orangefs_inode_s { ...@@ -192,7 +193,13 @@ struct orangefs_inode_s {
sector_t last_failed_block_index_read; sector_t last_failed_block_index_read;
unsigned long getattr_time; unsigned long getattr_time;
u32 getattr_mask; unsigned long mapping_time;
int attr_valid;
kuid_t attr_uid;
kgid_t attr_gid;
unsigned long bitlock;
DECLARE_HASHTABLE(xattr_cache, 4);
}; };
/* per superblock private orangefs info */ /* per superblock private orangefs info */
...@@ -217,6 +224,25 @@ struct orangefs_stats { ...@@ -217,6 +224,25 @@ struct orangefs_stats {
unsigned long writes; unsigned long writes;
}; };
struct orangefs_cached_xattr {
struct hlist_node node;
char key[ORANGEFS_MAX_XATTR_NAMELEN];
char val[ORANGEFS_MAX_XATTR_VALUELEN];
ssize_t length;
unsigned long timeout;
};
struct orangefs_write_range {
loff_t pos;
size_t len;
kuid_t uid;
kgid_t gid;
};
struct orangefs_read_options {
ssize_t blksiz;
};
extern struct orangefs_stats orangefs_stats; extern struct orangefs_stats orangefs_stats;
/* /*
...@@ -329,13 +355,15 @@ void fsid_key_table_finalize(void); ...@@ -329,13 +355,15 @@ void fsid_key_table_finalize(void);
/* /*
* defined in inode.c * defined in inode.c
*/ */
vm_fault_t orangefs_page_mkwrite(struct vm_fault *);
struct inode *orangefs_new_inode(struct super_block *sb, struct inode *orangefs_new_inode(struct super_block *sb,
struct inode *dir, struct inode *dir,
int mode, int mode,
dev_t dev, dev_t dev,
struct orangefs_object_kref *ref); struct orangefs_object_kref *ref);
int orangefs_setattr(struct dentry *dentry, struct iattr *iattr); int __orangefs_setattr(struct inode *, struct iattr *);
int orangefs_setattr(struct dentry *, struct iattr *);
int orangefs_getattr(const struct path *path, struct kstat *stat, int orangefs_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags); u32 request_mask, unsigned int flags);
...@@ -355,11 +383,6 @@ ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size); ...@@ -355,11 +383,6 @@ ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size);
struct inode *orangefs_iget(struct super_block *sb, struct inode *orangefs_iget(struct super_block *sb,
struct orangefs_object_kref *ref); struct orangefs_object_kref *ref);
ssize_t orangefs_inode_read(struct inode *inode,
struct iov_iter *iter,
loff_t *offset,
loff_t readahead_size);
/* /*
* defined in devorangefs-req.c * defined in devorangefs-req.c
*/ */
...@@ -370,6 +393,15 @@ void orangefs_dev_cleanup(void); ...@@ -370,6 +393,15 @@ void orangefs_dev_cleanup(void);
int is_daemon_in_service(void); int is_daemon_in_service(void);
bool __is_daemon_in_service(void); bool __is_daemon_in_service(void);
/*
* defined in file.c
*/
int orangefs_revalidate_mapping(struct inode *);
ssize_t wait_for_direct_io(enum ORANGEFS_io_type, struct inode *, loff_t *,
struct iov_iter *, size_t, loff_t, struct orangefs_write_range *, int *);
ssize_t do_readv_writev(enum ORANGEFS_io_type, struct file *, loff_t *,
struct iov_iter *);
/* /*
* defined in orangefs-utils.c * defined in orangefs-utils.c
*/ */
...@@ -386,12 +418,14 @@ int orangefs_inode_setxattr(struct inode *inode, ...@@ -386,12 +418,14 @@ int orangefs_inode_setxattr(struct inode *inode,
size_t size, size_t size,
int flags); int flags);
int orangefs_inode_getattr(struct inode *inode, int new, int bypass, #define ORANGEFS_GETATTR_NEW 1
u32 request_mask); #define ORANGEFS_GETATTR_SIZE 2
int orangefs_inode_getattr(struct inode *, int);
int orangefs_inode_check_changed(struct inode *inode); int orangefs_inode_check_changed(struct inode *inode);
int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr); int orangefs_inode_setattr(struct inode *inode);
bool orangefs_cancel_op_in_progress(struct orangefs_kernel_op_s *op); bool orangefs_cancel_op_in_progress(struct orangefs_kernel_op_s *op);
...@@ -400,6 +434,7 @@ int orangefs_normalize_to_errno(__s32 error_code); ...@@ -400,6 +434,7 @@ int orangefs_normalize_to_errno(__s32 error_code);
extern struct mutex orangefs_request_mutex; extern struct mutex orangefs_request_mutex;
extern int op_timeout_secs; extern int op_timeout_secs;
extern int slot_timeout_secs; extern int slot_timeout_secs;
extern int orangefs_cache_timeout_msecs;
extern int orangefs_dcache_timeout_msecs; extern int orangefs_dcache_timeout_msecs;
extern int orangefs_getattr_timeout_msecs; extern int orangefs_getattr_timeout_msecs;
extern struct list_head orangefs_superblocks; extern struct list_head orangefs_superblocks;
...@@ -426,6 +461,7 @@ extern const struct dentry_operations orangefs_dentry_operations; ...@@ -426,6 +461,7 @@ extern const struct dentry_operations orangefs_dentry_operations;
#define ORANGEFS_OP_CANCELLATION 4 /* this is a cancellation */ #define ORANGEFS_OP_CANCELLATION 4 /* this is a cancellation */
#define ORANGEFS_OP_NO_MUTEX 8 /* don't acquire request_mutex */ #define ORANGEFS_OP_NO_MUTEX 8 /* don't acquire request_mutex */
#define ORANGEFS_OP_ASYNC 16 /* Queue it, but don't wait */ #define ORANGEFS_OP_ASYNC 16 /* Queue it, but don't wait */
#define ORANGEFS_OP_WRITEBACK 32
int service_operation(struct orangefs_kernel_op_s *op, int service_operation(struct orangefs_kernel_op_s *op,
const char *op_name, const char *op_name,
......
...@@ -30,6 +30,7 @@ static ulong module_parm_debug_mask; ...@@ -30,6 +30,7 @@ static ulong module_parm_debug_mask;
__u64 orangefs_gossip_debug_mask; __u64 orangefs_gossip_debug_mask;
int op_timeout_secs = ORANGEFS_DEFAULT_OP_TIMEOUT_SECS; int op_timeout_secs = ORANGEFS_DEFAULT_OP_TIMEOUT_SECS;
int slot_timeout_secs = ORANGEFS_DEFAULT_SLOT_TIMEOUT_SECS; int slot_timeout_secs = ORANGEFS_DEFAULT_SLOT_TIMEOUT_SECS;
int orangefs_cache_timeout_msecs = 50;
int orangefs_dcache_timeout_msecs = 50; int orangefs_dcache_timeout_msecs = 50;
int orangefs_getattr_timeout_msecs = 50; int orangefs_getattr_timeout_msecs = 50;
......
...@@ -62,6 +62,14 @@ ...@@ -62,6 +62,14 @@
* Slots are requested and waited for, * Slots are requested and waited for,
* the wait times out after slot_timeout_secs. * the wait times out after slot_timeout_secs.
* *
* What: /sys/fs/orangefs/cache_timeout_msecs
* Date: Mar 2018
* Contact: Martin Brandenburg <martin@omnibond.com>
* Description:
* Time in milliseconds between which
* orangefs_revalidate_mapping will invalidate the page
* cache.
*
* What: /sys/fs/orangefs/dcache_timeout_msecs * What: /sys/fs/orangefs/dcache_timeout_msecs
* Date: Jul 2016 * Date: Jul 2016
* Contact: Martin Brandenburg <martin@omnibond.com> * Contact: Martin Brandenburg <martin@omnibond.com>
...@@ -221,6 +229,13 @@ static ssize_t sysfs_int_show(struct kobject *kobj, ...@@ -221,6 +229,13 @@ static ssize_t sysfs_int_show(struct kobject *kobj,
"%d\n", "%d\n",
slot_timeout_secs); slot_timeout_secs);
goto out; goto out;
} else if (!strcmp(attr->attr.name,
"cache_timeout_msecs")) {
rc = scnprintf(buf,
PAGE_SIZE,
"%d\n",
orangefs_cache_timeout_msecs);
goto out;
} else if (!strcmp(attr->attr.name, } else if (!strcmp(attr->attr.name,
"dcache_timeout_msecs")) { "dcache_timeout_msecs")) {
rc = scnprintf(buf, rc = scnprintf(buf,
...@@ -277,6 +292,9 @@ static ssize_t sysfs_int_store(struct kobject *kobj, ...@@ -277,6 +292,9 @@ static ssize_t sysfs_int_store(struct kobject *kobj,
} else if (!strcmp(attr->attr.name, "slot_timeout_secs")) { } else if (!strcmp(attr->attr.name, "slot_timeout_secs")) {
rc = kstrtoint(buf, 0, &slot_timeout_secs); rc = kstrtoint(buf, 0, &slot_timeout_secs);
goto out; goto out;
} else if (!strcmp(attr->attr.name, "cache_timeout_msecs")) {
rc = kstrtoint(buf, 0, &orangefs_cache_timeout_msecs);
goto out;
} else if (!strcmp(attr->attr.name, "dcache_timeout_msecs")) { } else if (!strcmp(attr->attr.name, "dcache_timeout_msecs")) {
rc = kstrtoint(buf, 0, &orangefs_dcache_timeout_msecs); rc = kstrtoint(buf, 0, &orangefs_dcache_timeout_msecs);
goto out; goto out;
...@@ -818,6 +836,9 @@ static struct orangefs_attribute op_timeout_secs_attribute = ...@@ -818,6 +836,9 @@ static struct orangefs_attribute op_timeout_secs_attribute =
static struct orangefs_attribute slot_timeout_secs_attribute = static struct orangefs_attribute slot_timeout_secs_attribute =
__ATTR(slot_timeout_secs, 0664, sysfs_int_show, sysfs_int_store); __ATTR(slot_timeout_secs, 0664, sysfs_int_show, sysfs_int_store);
static struct orangefs_attribute cache_timeout_msecs_attribute =
__ATTR(cache_timeout_msecs, 0664, sysfs_int_show, sysfs_int_store);
static struct orangefs_attribute dcache_timeout_msecs_attribute = static struct orangefs_attribute dcache_timeout_msecs_attribute =
__ATTR(dcache_timeout_msecs, 0664, sysfs_int_show, sysfs_int_store); __ATTR(dcache_timeout_msecs, 0664, sysfs_int_show, sysfs_int_store);
...@@ -861,6 +882,7 @@ static struct orangefs_attribute perf_time_interval_secs_attribute = ...@@ -861,6 +882,7 @@ static struct orangefs_attribute perf_time_interval_secs_attribute =
static struct attribute *orangefs_default_attrs[] = { static struct attribute *orangefs_default_attrs[] = {
&op_timeout_secs_attribute.attr, &op_timeout_secs_attribute.attr,
&slot_timeout_secs_attribute.attr, &slot_timeout_secs_attribute.attr,
&cache_timeout_msecs_attribute.attr,
&dcache_timeout_msecs_attribute.attr, &dcache_timeout_msecs_attribute.attr,
&getattr_timeout_msecs_attribute.attr, &getattr_timeout_msecs_attribute.attr,
&readahead_count_attribute.attr, &readahead_count_attribute.attr,
......
This diff is collapsed.
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "orangefs-bufmap.h" #include "orangefs-bufmap.h"
#include <linux/parser.h> #include <linux/parser.h>
#include <linux/hashtable.h>
/* a cache for orangefs-inode objects (i.e. orangefs inode private data) */ /* a cache for orangefs-inode objects (i.e. orangefs inode private data) */
static struct kmem_cache *orangefs_inode_cache; static struct kmem_cache *orangefs_inode_cache;
...@@ -126,7 +127,17 @@ static struct inode *orangefs_alloc_inode(struct super_block *sb) ...@@ -126,7 +127,17 @@ static struct inode *orangefs_alloc_inode(struct super_block *sb)
static void orangefs_free_inode(struct inode *inode) static void orangefs_free_inode(struct inode *inode)
{ {
kmem_cache_free(orangefs_inode_cache, ORANGEFS_I(inode)); struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
struct orangefs_cached_xattr *cx;
struct hlist_node *tmp;
int i;
hash_for_each_safe(orangefs_inode->xattr_cache, i, tmp, cx, node) {
hlist_del(&cx->node);
kfree(cx);
}
kmem_cache_free(orangefs_inode_cache, orangefs_inode);
} }
static void orangefs_destroy_inode(struct inode *inode) static void orangefs_destroy_inode(struct inode *inode)
...@@ -138,6 +149,13 @@ static void orangefs_destroy_inode(struct inode *inode) ...@@ -138,6 +149,13 @@ static void orangefs_destroy_inode(struct inode *inode)
__func__, orangefs_inode, get_khandle_from_ino(inode)); __func__, orangefs_inode, get_khandle_from_ino(inode));
} }
static int orangefs_write_inode(struct inode *inode,
struct writeback_control *wbc)
{
gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_write_inode\n");
return orangefs_inode_setattr(inode);
}
/* /*
* NOTE: information filled in here is typically reflected in the * NOTE: information filled in here is typically reflected in the
* output of the system command 'df' * output of the system command 'df'
...@@ -297,6 +315,7 @@ static const struct super_operations orangefs_s_ops = { ...@@ -297,6 +315,7 @@ static const struct super_operations orangefs_s_ops = {
.alloc_inode = orangefs_alloc_inode, .alloc_inode = orangefs_alloc_inode,
.free_inode = orangefs_free_inode, .free_inode = orangefs_free_inode,
.destroy_inode = orangefs_destroy_inode, .destroy_inode = orangefs_destroy_inode,
.write_inode = orangefs_write_inode,
.drop_inode = generic_delete_inode, .drop_inode = generic_delete_inode,
.statfs = orangefs_statfs, .statfs = orangefs_statfs,
.remount_fs = orangefs_remount_fs, .remount_fs = orangefs_remount_fs,
...@@ -394,15 +413,11 @@ static int orangefs_fill_sb(struct super_block *sb, ...@@ -394,15 +413,11 @@ static int orangefs_fill_sb(struct super_block *sb,
struct orangefs_fs_mount_response *fs_mount, struct orangefs_fs_mount_response *fs_mount,
void *data, int silent) void *data, int silent)
{ {
int ret = -EINVAL; int ret;
struct inode *root = NULL; struct inode *root;
struct dentry *root_dentry = NULL; struct dentry *root_dentry;
struct orangefs_object_kref root_object; struct orangefs_object_kref root_object;
/* alloc and init our private orangefs sb info */
sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL);
if (!ORANGEFS_SB(sb))
return -ENOMEM;
ORANGEFS_SB(sb)->sb = sb; ORANGEFS_SB(sb)->sb = sb;
ORANGEFS_SB(sb)->root_khandle = fs_mount->root_khandle; ORANGEFS_SB(sb)->root_khandle = fs_mount->root_khandle;
...@@ -425,6 +440,10 @@ static int orangefs_fill_sb(struct super_block *sb, ...@@ -425,6 +440,10 @@ static int orangefs_fill_sb(struct super_block *sb,
sb->s_blocksize_bits = PAGE_SHIFT; sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_maxbytes = MAX_LFS_FILESIZE;
ret = super_setup_bdi(sb);
if (ret)
return ret;
root_object.khandle = ORANGEFS_SB(sb)->root_khandle; root_object.khandle = ORANGEFS_SB(sb)->root_khandle;
root_object.fs_id = ORANGEFS_SB(sb)->fs_id; root_object.fs_id = ORANGEFS_SB(sb)->fs_id;
gossip_debug(GOSSIP_SUPER_DEBUG, gossip_debug(GOSSIP_SUPER_DEBUG,
...@@ -503,6 +522,13 @@ struct dentry *orangefs_mount(struct file_system_type *fst, ...@@ -503,6 +522,13 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
goto free_op; goto free_op;
} }
/* alloc and init our private orangefs sb info */
sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL);
if (!ORANGEFS_SB(sb)) {
d = ERR_PTR(-ENOMEM);
goto free_op;
}
ret = orangefs_fill_sb(sb, ret = orangefs_fill_sb(sb,
&new_op->downcall.resp.fs_mount, data, &new_op->downcall.resp.fs_mount, data,
flags & SB_SILENT ? 1 : 0); flags & SB_SILENT ? 1 : 0);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op, static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op,
long timeout, long timeout,
bool interruptible) int flags)
__acquires(op->lock); __acquires(op->lock);
static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *op) static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *op)
__releases(op->lock); __releases(op->lock);
...@@ -143,9 +143,7 @@ int service_operation(struct orangefs_kernel_op_s *op, ...@@ -143,9 +143,7 @@ int service_operation(struct orangefs_kernel_op_s *op,
if (!(flags & ORANGEFS_OP_NO_MUTEX)) if (!(flags & ORANGEFS_OP_NO_MUTEX))
mutex_unlock(&orangefs_request_mutex); mutex_unlock(&orangefs_request_mutex);
ret = wait_for_matching_downcall(op, timeout, ret = wait_for_matching_downcall(op, timeout, flags);
flags & ORANGEFS_OP_INTERRUPTIBLE);
gossip_debug(GOSSIP_WAIT_DEBUG, gossip_debug(GOSSIP_WAIT_DEBUG,
"%s: wait_for_matching_downcall returned %d for %p\n", "%s: wait_for_matching_downcall returned %d for %p\n",
__func__, __func__,
...@@ -319,10 +317,12 @@ static void ...@@ -319,10 +317,12 @@ static void
*/ */
static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op, static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op,
long timeout, long timeout,
bool interruptible) int flags)
__acquires(op->lock) __acquires(op->lock)
{ {
long n; long n;
int writeback = flags & ORANGEFS_OP_WRITEBACK,
interruptible = flags & ORANGEFS_OP_INTERRUPTIBLE;
/* /*
* There's a "schedule_timeout" inside of these wait * There's a "schedule_timeout" inside of these wait
...@@ -330,10 +330,12 @@ static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op, ...@@ -330,10 +330,12 @@ static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op,
* user process that needs something done and is being * user process that needs something done and is being
* manipulated by the client-core process. * manipulated by the client-core process.
*/ */
if (interruptible) if (writeback)
n = wait_for_completion_io_timeout(&op->waitq, timeout);
else if (!writeback && interruptible)
n = wait_for_completion_interruptible_timeout(&op->waitq, n = wait_for_completion_interruptible_timeout(&op->waitq,
timeout); timeout);
else else /* !writeback && !interruptible but compiler complains */
n = wait_for_completion_killable_timeout(&op->waitq, timeout); n = wait_for_completion_killable_timeout(&op->waitq, timeout);
spin_lock(&op->lock); spin_lock(&op->lock);
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* (C) 2001 Clemson University and The University of Chicago * (C) 2001 Clemson University and The University of Chicago
* Copyright 2018 Omnibond Systems, L.L.C.
* *
* See COPYING in top-level directory. * See COPYING in top-level directory.
*/ */
...@@ -14,7 +15,7 @@ ...@@ -14,7 +15,7 @@
#include "orangefs-bufmap.h" #include "orangefs-bufmap.h"
#include <linux/posix_acl_xattr.h> #include <linux/posix_acl_xattr.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/hashtable.h>
#define SYSTEM_ORANGEFS_KEY "system.pvfs2." #define SYSTEM_ORANGEFS_KEY "system.pvfs2."
#define SYSTEM_ORANGEFS_KEY_LEN 13 #define SYSTEM_ORANGEFS_KEY_LEN 13
...@@ -50,6 +51,35 @@ static inline int convert_to_internal_xattr_flags(int setxattr_flags) ...@@ -50,6 +51,35 @@ static inline int convert_to_internal_xattr_flags(int setxattr_flags)
return internal_flag; return internal_flag;
} }
static unsigned int xattr_key(const char *key)
{
unsigned int i = 0;
while (key)
i += *key++;
return i % 16;
}
static struct orangefs_cached_xattr *find_cached_xattr(struct inode *inode,
const char *key)
{
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
struct orangefs_cached_xattr *cx;
struct hlist_head *h;
struct hlist_node *tmp;
h = &orangefs_inode->xattr_cache[xattr_key(key)];
if (hlist_empty(h))
return NULL;
hlist_for_each_entry_safe(cx, tmp, h, node) {
/* if (!time_before(jiffies, cx->timeout)) {
hlist_del(&cx->node);
kfree(cx);
continue;
}*/
if (!strcmp(cx->key, key))
return cx;
}
return NULL;
}
/* /*
* Tries to get a specified key's attributes of a given * Tries to get a specified key's attributes of a given
...@@ -65,6 +95,7 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name, ...@@ -65,6 +95,7 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
{ {
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
struct orangefs_kernel_op_s *new_op = NULL; struct orangefs_kernel_op_s *new_op = NULL;
struct orangefs_cached_xattr *cx;
ssize_t ret = -ENOMEM; ssize_t ret = -ENOMEM;
ssize_t length = 0; ssize_t length = 0;
int fsuid; int fsuid;
...@@ -93,6 +124,27 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name, ...@@ -93,6 +124,27 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
down_read(&orangefs_inode->xattr_sem); down_read(&orangefs_inode->xattr_sem);
cx = find_cached_xattr(inode, name);
if (cx && time_before(jiffies, cx->timeout)) {
if (cx->length == -1) {
ret = -ENODATA;
goto out_unlock;
} else {
if (size == 0) {
ret = cx->length;
goto out_unlock;
}
if (cx->length > size) {
ret = -ERANGE;
goto out_unlock;
}
memcpy(buffer, cx->val, cx->length);
memset(buffer + cx->length, 0, size - cx->length);
ret = cx->length;
goto out_unlock;
}
}
new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR); new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR);
if (!new_op) if (!new_op)
goto out_unlock; goto out_unlock;
...@@ -117,6 +169,15 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name, ...@@ -117,6 +169,15 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
" does not exist!\n", " does not exist!\n",
get_khandle_from_ino(inode), get_khandle_from_ino(inode),
(char *)new_op->upcall.req.getxattr.key); (char *)new_op->upcall.req.getxattr.key);
cx = kmalloc(sizeof *cx, GFP_KERNEL);
if (cx) {
strcpy(cx->key, name);
cx->length = -1;
cx->timeout = jiffies +
orangefs_getattr_timeout_msecs*HZ/1000;
hash_add(orangefs_inode->xattr_cache, &cx->node,
xattr_key(cx->key));
}
} }
goto out_release_op; goto out_release_op;
} }
...@@ -156,6 +217,23 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name, ...@@ -156,6 +217,23 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
ret = length; ret = length;
if (cx) {
strcpy(cx->key, name);
memcpy(cx->val, buffer, length);
cx->length = length;
cx->timeout = jiffies + HZ;
} else {
cx = kmalloc(sizeof *cx, GFP_KERNEL);
if (cx) {
strcpy(cx->key, name);
memcpy(cx->val, buffer, length);
cx->length = length;
cx->timeout = jiffies + HZ;
hash_add(orangefs_inode->xattr_cache, &cx->node,
xattr_key(cx->key));
}
}
out_release_op: out_release_op:
op_release(new_op); op_release(new_op);
out_unlock: out_unlock:
...@@ -168,6 +246,9 @@ static int orangefs_inode_removexattr(struct inode *inode, const char *name, ...@@ -168,6 +246,9 @@ static int orangefs_inode_removexattr(struct inode *inode, const char *name,
{ {
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
struct orangefs_kernel_op_s *new_op = NULL; struct orangefs_kernel_op_s *new_op = NULL;
struct orangefs_cached_xattr *cx;
struct hlist_head *h;
struct hlist_node *tmp;
int ret = -ENOMEM; int ret = -ENOMEM;
if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN)
...@@ -209,6 +290,16 @@ static int orangefs_inode_removexattr(struct inode *inode, const char *name, ...@@ -209,6 +290,16 @@ static int orangefs_inode_removexattr(struct inode *inode, const char *name,
"orangefs_inode_removexattr: returning %d\n", ret); "orangefs_inode_removexattr: returning %d\n", ret);
op_release(new_op); op_release(new_op);
h = &orangefs_inode->xattr_cache[xattr_key(name)];
hlist_for_each_entry_safe(cx, tmp, h, node) {
if (!strcmp(cx->key, name)) {
hlist_del(&cx->node);
kfree(cx);
break;
}
}
out_unlock: out_unlock:
up_write(&orangefs_inode->xattr_sem); up_write(&orangefs_inode->xattr_sem);
return ret; return ret;
...@@ -226,6 +317,9 @@ int orangefs_inode_setxattr(struct inode *inode, const char *name, ...@@ -226,6 +317,9 @@ int orangefs_inode_setxattr(struct inode *inode, const char *name,
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
struct orangefs_kernel_op_s *new_op; struct orangefs_kernel_op_s *new_op;
int internal_flag = 0; int internal_flag = 0;
struct orangefs_cached_xattr *cx;
struct hlist_head *h;
struct hlist_node *tmp;
int ret = -ENOMEM; int ret = -ENOMEM;
gossip_debug(GOSSIP_XATTR_DEBUG, gossip_debug(GOSSIP_XATTR_DEBUG,
...@@ -287,6 +381,16 @@ int orangefs_inode_setxattr(struct inode *inode, const char *name, ...@@ -287,6 +381,16 @@ int orangefs_inode_setxattr(struct inode *inode, const char *name,
/* when request is serviced properly, free req op struct */ /* when request is serviced properly, free req op struct */
op_release(new_op); op_release(new_op);
h = &orangefs_inode->xattr_cache[xattr_key(name)];
hlist_for_each_entry_safe(cx, tmp, h, node) {
if (!strcmp(cx->key, name)) {
hlist_del(&cx->node);
kfree(cx);
break;
}
}
out_unlock: out_unlock:
up_write(&orangefs_inode->xattr_sem); up_write(&orangefs_inode->xattr_sem);
return ret; return ret;
......
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