mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 13:41:51 +00:00
orangefs: implement statx
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>
This commit is contained in:
parent
7b796ae370
commit
68a24a6cc4
@ -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. */
|
/* Make sure generic_write_checks sees an up to date inode size. */
|
||||||
if (file->f_flags & O_APPEND) {
|
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)
|
if (rc == -ESTALE)
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@ -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,
|
* NOTE: We are only interested in file size here,
|
||||||
* so we set mask accordingly.
|
* 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)
|
if (ret == -ESTALE)
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -161,7 +161,7 @@ static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
|
|||||||
iattr->ia_size);
|
iattr->ia_size);
|
||||||
|
|
||||||
/* Ensure that we have a up to date size, so we know if it changed. */
|
/* 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)
|
if (ret == -ESTALE)
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -256,13 +256,19 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
|
|||||||
"orangefs_getattr: called on %pd\n",
|
"orangefs_getattr: called on %pd\n",
|
||||||
path->dentry);
|
path->dentry);
|
||||||
|
|
||||||
ret = orangefs_inode_getattr(inode, 0, 0);
|
ret = orangefs_inode_getattr(inode, 0, 0, request_mask);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
generic_fillattr(inode, stat);
|
generic_fillattr(inode, stat);
|
||||||
|
|
||||||
/* override block size reported to stat */
|
/* override block size reported to stat */
|
||||||
orangefs_inode = ORANGEFS_I(inode);
|
orangefs_inode = ORANGEFS_I(inode);
|
||||||
stat->blksize = orangefs_inode->blksize;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -277,7 +283,7 @@ int orangefs_permission(struct inode *inode, int mask)
|
|||||||
gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);
|
gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);
|
||||||
|
|
||||||
/* Make sure the permission (and other common attrs) are up to date. */
|
/* 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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -375,7 +381,7 @@ struct inode *orangefs_iget(struct super_block *sb, struct orangefs_object_kref
|
|||||||
if (!inode || !(inode->i_state & I_NEW))
|
if (!inode || !(inode->i_state & I_NEW))
|
||||||
return inode;
|
return inode;
|
||||||
|
|
||||||
error = orangefs_inode_getattr(inode, 1, 1);
|
error = orangefs_inode_getattr(inode, 1, 1, STATX_ALL);
|
||||||
if (error) {
|
if (error) {
|
||||||
iget_failed(inode);
|
iget_failed(inode);
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
@ -420,7 +426,7 @@ struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
|
|||||||
orangefs_set_inode(inode, ref);
|
orangefs_set_inode(inode, ref);
|
||||||
inode->i_ino = hash; /* needed for stat etc */
|
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)
|
if (error)
|
||||||
goto out_iput;
|
goto out_iput;
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ static int orangefs_create(struct inode *dir,
|
|||||||
unlock_new_inode(inode);
|
unlock_new_inode(inode);
|
||||||
orangefs_set_timeout(dentry);
|
orangefs_set_timeout(dentry);
|
||||||
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
|
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",
|
||||||
@ -322,6 +323,7 @@ static int orangefs_symlink(struct inode *dir,
|
|||||||
unlock_new_inode(inode);
|
unlock_new_inode(inode);
|
||||||
orangefs_set_timeout(dentry);
|
orangefs_set_timeout(dentry);
|
||||||
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
|
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",
|
||||||
@ -386,6 +388,7 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
|
|||||||
unlock_new_inode(inode);
|
unlock_new_inode(inode);
|
||||||
orangefs_set_timeout(dentry);
|
orangefs_set_timeout(dentry);
|
||||||
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
|
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",
|
||||||
|
@ -215,6 +215,7 @@ struct orangefs_inode_s {
|
|||||||
unsigned long pinode_flags;
|
unsigned long pinode_flags;
|
||||||
|
|
||||||
unsigned long getattr_time;
|
unsigned long getattr_time;
|
||||||
|
u32 getattr_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define P_ATIME_FLAG 0
|
#define P_ATIME_FLAG 0
|
||||||
@ -495,7 +496,8 @@ 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);
|
int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
|
||||||
|
u32 request_mask);
|
||||||
|
|
||||||
int orangefs_inode_check_changed(struct inode *inode);
|
int orangefs_inode_check_changed(struct inode *inode);
|
||||||
|
|
||||||
|
@ -251,7 +251,8 @@ static int orangefs_inode_is_stale(struct inode *inode, int new,
|
|||||||
return 0;
|
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_inode_s *orangefs_inode = ORANGEFS_I(inode);
|
||||||
struct orangefs_kernel_op_s *new_op;
|
struct orangefs_kernel_op_s *new_op;
|
||||||
@ -262,7 +263,13 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
|
|||||||
get_khandle_from_ino(inode));
|
get_khandle_from_ino(inode));
|
||||||
|
|
||||||
if (!new && !bypass) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +277,15 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
|
|||||||
if (!new_op)
|
if (!new_op)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
new_op->upcall.req.getattr.refn = orangefs_inode->refn;
|
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__,
|
ret = service_operation(new_op, __func__,
|
||||||
get_interruptible_flag(inode));
|
get_interruptible_flag(inode));
|
||||||
@ -291,25 +306,29 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
|
|||||||
case S_IFREG:
|
case S_IFREG:
|
||||||
inode->i_flags = orangefs_inode_flags(&new_op->
|
inode->i_flags = orangefs_inode_flags(&new_op->
|
||||||
downcall.resp.getattr.attributes);
|
downcall.resp.getattr.attributes);
|
||||||
inode_size = (loff_t)new_op->
|
if (request_mask & STATX_SIZE || new) {
|
||||||
downcall.resp.getattr.attributes.size;
|
inode_size = (loff_t)new_op->
|
||||||
rounded_up_size =
|
downcall.resp.getattr.attributes.size;
|
||||||
(inode_size + (4096 - (inode_size % 4096)));
|
rounded_up_size =
|
||||||
inode->i_size = inode_size;
|
(inode_size + (4096 - (inode_size % 4096)));
|
||||||
orangefs_inode->blksize =
|
inode->i_size = inode_size;
|
||||||
new_op->downcall.resp.getattr.attributes.blksize;
|
orangefs_inode->blksize =
|
||||||
spin_lock(&inode->i_lock);
|
new_op->downcall.resp.getattr.attributes.blksize;
|
||||||
inode->i_bytes = inode_size;
|
spin_lock(&inode->i_lock);
|
||||||
inode->i_blocks =
|
inode->i_bytes = inode_size;
|
||||||
(unsigned long)(rounded_up_size / 512);
|
inode->i_blocks =
|
||||||
spin_unlock(&inode->i_lock);
|
(unsigned long)(rounded_up_size / 512);
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case S_IFDIR:
|
case S_IFDIR:
|
||||||
inode->i_size = PAGE_SIZE;
|
if (request_mask & STATX_SIZE || new) {
|
||||||
orangefs_inode->blksize = i_blocksize(inode);
|
inode->i_size = PAGE_SIZE;
|
||||||
spin_lock(&inode->i_lock);
|
orangefs_inode->blksize = i_blocksize(inode);
|
||||||
inode_set_bytes(inode, inode->i_size);
|
spin_lock(&inode->i_lock);
|
||||||
spin_unlock(&inode->i_lock);
|
inode_set_bytes(inode, inode->i_size);
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
|
}
|
||||||
set_nlink(inode, 1);
|
set_nlink(inode, 1);
|
||||||
break;
|
break;
|
||||||
case S_IFLNK:
|
case S_IFLNK:
|
||||||
@ -349,6 +368,10 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
|
|||||||
|
|
||||||
orangefs_inode->getattr_time = jiffies +
|
orangefs_inode->getattr_time = jiffies +
|
||||||
orangefs_getattr_timeout_msecs*HZ/1000;
|
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;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
op_release(new_op);
|
op_release(new_op);
|
||||||
|
Loading…
Reference in New Issue
Block a user