Skip to content

Commit

Permalink
orangefs: implement statx
Browse files Browse the repository at this point in the history
Fortunately OrangeFS has had a getattr request mask for a long time.

The server basically has two difficulty levels for attributes.  Fetching
any attribute except size requires communicating with the metadata
server for that handle.  Since all the attributes are right there, it
makes sense to return them all.  Fetching the size requires
communicating with every I/O server (that the file is distributed
across).  Therefore if asked for anything except size, get everything
except size, and if asked for size, get everything.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
  • Loading branch information
Martin Brandenburg authored and hubcapsc committed Apr 26, 2017
1 parent 7b796ae commit 68a24a6
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 28 deletions.
6 changes: 4 additions & 2 deletions fs/orangefs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,8 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *ite

/* Make sure generic_write_checks sees an up to date inode size. */
if (file->f_flags & O_APPEND) {
rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1);
rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1,
STATX_SIZE);
if (rc == -ESTALE)
rc = -EIO;
if (rc) {
Expand Down Expand Up @@ -693,7 +694,8 @@ static loff_t orangefs_file_llseek(struct file *file, loff_t offset, int origin)
* NOTE: We are only interested in file size here,
* so we set mask accordingly.
*/
ret = orangefs_inode_getattr(file->f_mapping->host, 0, 1);
ret = orangefs_inode_getattr(file->f_mapping->host, 0, 1,
STATX_SIZE);
if (ret == -ESTALE)
ret = -EIO;
if (ret) {
Expand Down
16 changes: 11 additions & 5 deletions fs/orangefs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
iattr->ia_size);

/* Ensure that we have a up to date size, so we know if it changed. */
ret = orangefs_inode_getattr(inode, 0, 1);
ret = orangefs_inode_getattr(inode, 0, 1, STATX_SIZE);
if (ret == -ESTALE)
ret = -EIO;
if (ret) {
Expand Down Expand Up @@ -256,13 +256,19 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
"orangefs_getattr: called on %pd\n",
path->dentry);

ret = orangefs_inode_getattr(inode, 0, 0);
ret = orangefs_inode_getattr(inode, 0, 0, request_mask);
if (ret == 0) {
generic_fillattr(inode, stat);

/* override block size reported to stat */
orangefs_inode = ORANGEFS_I(inode);
stat->blksize = orangefs_inode->blksize;

if (request_mask & STATX_SIZE)
stat->result_mask = STATX_BASIC_STATS;
else
stat->result_mask = STATX_BASIC_STATS &
~STATX_SIZE;
}
return ret;
}
Expand All @@ -277,7 +283,7 @@ int orangefs_permission(struct inode *inode, int mask)
gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);

/* Make sure the permission (and other common attrs) are up to date. */
ret = orangefs_inode_getattr(inode, 0, 0);
ret = orangefs_inode_getattr(inode, 0, 0, STATX_MODE);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -375,7 +381,7 @@ struct inode *orangefs_iget(struct super_block *sb, struct orangefs_object_kref
if (!inode || !(inode->i_state & I_NEW))
return inode;

error = orangefs_inode_getattr(inode, 1, 1);
error = orangefs_inode_getattr(inode, 1, 1, STATX_ALL);
if (error) {
iget_failed(inode);
return ERR_PTR(error);
Expand Down Expand Up @@ -420,7 +426,7 @@ struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
orangefs_set_inode(inode, ref);
inode->i_ino = hash; /* needed for stat etc */

error = orangefs_inode_getattr(inode, 1, 1);
error = orangefs_inode_getattr(inode, 1, 1, STATX_ALL);
if (error)
goto out_iput;

Expand Down
3 changes: 3 additions & 0 deletions fs/orangefs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ static int orangefs_create(struct inode *dir,
unlock_new_inode(inode);
orangefs_set_timeout(dentry);
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;

gossip_debug(GOSSIP_NAME_DEBUG,
"%s: dentry instantiated for %pd\n",
Expand Down Expand Up @@ -322,6 +323,7 @@ static int orangefs_symlink(struct inode *dir,
unlock_new_inode(inode);
orangefs_set_timeout(dentry);
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;

gossip_debug(GOSSIP_NAME_DEBUG,
"Inode (Symlink) %pU -> %pd\n",
Expand Down Expand Up @@ -386,6 +388,7 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
unlock_new_inode(inode);
orangefs_set_timeout(dentry);
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;

gossip_debug(GOSSIP_NAME_DEBUG,
"Inode (Directory) %pU -> %pd\n",
Expand Down
4 changes: 3 additions & 1 deletion fs/orangefs/orangefs-kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ struct orangefs_inode_s {
unsigned long pinode_flags;

unsigned long getattr_time;
u32 getattr_mask;
};

#define P_ATIME_FLAG 0
Expand Down Expand Up @@ -495,7 +496,8 @@ int orangefs_inode_setxattr(struct inode *inode,
size_t size,
int flags);

int orangefs_inode_getattr(struct inode *inode, int new, int bypass);
int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
u32 request_mask);

int orangefs_inode_check_changed(struct inode *inode);

Expand Down
63 changes: 43 additions & 20 deletions fs/orangefs/orangefs-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ static int orangefs_inode_is_stale(struct inode *inode, int new,
return 0;
}

int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
u32 request_mask)
{
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
struct orangefs_kernel_op_s *new_op;
Expand All @@ -262,15 +263,29 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
get_khandle_from_ino(inode));

if (!new && !bypass) {
if (time_before(jiffies, orangefs_inode->getattr_time))
/*
* Must have all the attributes in the mask and be within cache
* time.
*/
if ((request_mask & orangefs_inode->getattr_mask) ==
request_mask &&
time_before(jiffies, orangefs_inode->getattr_time))
return 0;
}

new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
if (!new_op)
return -ENOMEM;
new_op->upcall.req.getattr.refn = orangefs_inode->refn;
new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
/*
* Size is the hardest attribute to get. The incremental cost of any
* other attribute is essentially zero.
*/
if (request_mask & STATX_SIZE || new)
new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
else
new_op->upcall.req.getattr.mask =
ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;

ret = service_operation(new_op, __func__,
get_interruptible_flag(inode));
Expand All @@ -291,25 +306,29 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
case S_IFREG:
inode->i_flags = orangefs_inode_flags(&new_op->
downcall.resp.getattr.attributes);
inode_size = (loff_t)new_op->
downcall.resp.getattr.attributes.size;
rounded_up_size =
(inode_size + (4096 - (inode_size % 4096)));
inode->i_size = inode_size;
orangefs_inode->blksize =
new_op->downcall.resp.getattr.attributes.blksize;
spin_lock(&inode->i_lock);
inode->i_bytes = inode_size;
inode->i_blocks =
(unsigned long)(rounded_up_size / 512);
spin_unlock(&inode->i_lock);
if (request_mask & STATX_SIZE || new) {
inode_size = (loff_t)new_op->
downcall.resp.getattr.attributes.size;
rounded_up_size =
(inode_size + (4096 - (inode_size % 4096)));
inode->i_size = inode_size;
orangefs_inode->blksize =
new_op->downcall.resp.getattr.attributes.blksize;
spin_lock(&inode->i_lock);
inode->i_bytes = inode_size;
inode->i_blocks =
(unsigned long)(rounded_up_size / 512);
spin_unlock(&inode->i_lock);
}
break;
case S_IFDIR:
inode->i_size = PAGE_SIZE;
orangefs_inode->blksize = i_blocksize(inode);
spin_lock(&inode->i_lock);
inode_set_bytes(inode, inode->i_size);
spin_unlock(&inode->i_lock);
if (request_mask & STATX_SIZE || new) {
inode->i_size = PAGE_SIZE;
orangefs_inode->blksize = i_blocksize(inode);
spin_lock(&inode->i_lock);
inode_set_bytes(inode, inode->i_size);
spin_unlock(&inode->i_lock);
}
set_nlink(inode, 1);
break;
case S_IFLNK:
Expand Down Expand Up @@ -349,6 +368,10 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)

orangefs_inode->getattr_time = jiffies +
orangefs_getattr_timeout_msecs*HZ/1000;
if (request_mask & STATX_SIZE || new)
orangefs_inode->getattr_mask = STATX_BASIC_STATS;
else
orangefs_inode->getattr_mask = STATX_BASIC_STATS & ~STATX_SIZE;
ret = 0;
out:
op_release(new_op);
Expand Down

0 comments on commit 68a24a6

Please sign in to comment.