Skip to content

Commit 68a24a6

Browse files
Martin Brandenburghubcapsc
authored andcommitted
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 <[email protected]> Signed-off-by: Mike Marshall <[email protected]>
1 parent 7b796ae commit 68a24a6

File tree

5 files changed

+64
-28
lines changed

5 files changed

+64
-28
lines changed

fs/orangefs/file.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,8 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *ite
475475

476476
/* Make sure generic_write_checks sees an up to date inode size. */
477477
if (file->f_flags & O_APPEND) {
478-
rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1);
478+
rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1,
479+
STATX_SIZE);
479480
if (rc == -ESTALE)
480481
rc = -EIO;
481482
if (rc) {
@@ -693,7 +694,8 @@ static loff_t orangefs_file_llseek(struct file *file, loff_t offset, int origin)
693694
* NOTE: We are only interested in file size here,
694695
* so we set mask accordingly.
695696
*/
696-
ret = orangefs_inode_getattr(file->f_mapping->host, 0, 1);
697+
ret = orangefs_inode_getattr(file->f_mapping->host, 0, 1,
698+
STATX_SIZE);
697699
if (ret == -ESTALE)
698700
ret = -EIO;
699701
if (ret) {

fs/orangefs/inode.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
161161
iattr->ia_size);
162162

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

259-
ret = orangefs_inode_getattr(inode, 0, 0);
259+
ret = orangefs_inode_getattr(inode, 0, 0, request_mask);
260260
if (ret == 0) {
261261
generic_fillattr(inode, stat);
262262

263263
/* override block size reported to stat */
264264
orangefs_inode = ORANGEFS_I(inode);
265265
stat->blksize = orangefs_inode->blksize;
266+
267+
if (request_mask & STATX_SIZE)
268+
stat->result_mask = STATX_BASIC_STATS;
269+
else
270+
stat->result_mask = STATX_BASIC_STATS &
271+
~STATX_SIZE;
266272
}
267273
return ret;
268274
}
@@ -277,7 +283,7 @@ int orangefs_permission(struct inode *inode, int mask)
277283
gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);
278284

279285
/* Make sure the permission (and other common attrs) are up to date. */
280-
ret = orangefs_inode_getattr(inode, 0, 0);
286+
ret = orangefs_inode_getattr(inode, 0, 0, STATX_MODE);
281287
if (ret < 0)
282288
return ret;
283289

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

378-
error = orangefs_inode_getattr(inode, 1, 1);
384+
error = orangefs_inode_getattr(inode, 1, 1, STATX_ALL);
379385
if (error) {
380386
iget_failed(inode);
381387
return ERR_PTR(error);
@@ -420,7 +426,7 @@ struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
420426
orangefs_set_inode(inode, ref);
421427
inode->i_ino = hash; /* needed for stat etc */
422428

423-
error = orangefs_inode_getattr(inode, 1, 1);
429+
error = orangefs_inode_getattr(inode, 1, 1, STATX_ALL);
424430
if (error)
425431
goto out_iput;
426432

fs/orangefs/namei.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ static int orangefs_create(struct inode *dir,
7474
unlock_new_inode(inode);
7575
orangefs_set_timeout(dentry);
7676
ORANGEFS_I(inode)->getattr_time = jiffies - 1;
77+
ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
7778

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

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

390393
gossip_debug(GOSSIP_NAME_DEBUG,
391394
"Inode (Directory) %pU -> %pd\n",

fs/orangefs/orangefs-kernel.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ struct orangefs_inode_s {
215215
unsigned long pinode_flags;
216216

217217
unsigned long getattr_time;
218+
u32 getattr_mask;
218219
};
219220

220221
#define P_ATIME_FLAG 0
@@ -495,7 +496,8 @@ int orangefs_inode_setxattr(struct inode *inode,
495496
size_t size,
496497
int flags);
497498

498-
int orangefs_inode_getattr(struct inode *inode, int new, int bypass);
499+
int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
500+
u32 request_mask);
499501

500502
int orangefs_inode_check_changed(struct inode *inode);
501503

fs/orangefs/orangefs-utils.c

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,8 @@ static int orangefs_inode_is_stale(struct inode *inode, int new,
251251
return 0;
252252
}
253253

254-
int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
254+
int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
255+
u32 request_mask)
255256
{
256257
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
257258
struct orangefs_kernel_op_s *new_op;
@@ -262,15 +263,29 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
262263
get_khandle_from_ino(inode));
263264

264265
if (!new && !bypass) {
265-
if (time_before(jiffies, orangefs_inode->getattr_time))
266+
/*
267+
* Must have all the attributes in the mask and be within cache
268+
* time.
269+
*/
270+
if ((request_mask & orangefs_inode->getattr_mask) ==
271+
request_mask &&
272+
time_before(jiffies, orangefs_inode->getattr_time))
266273
return 0;
267274
}
268275

269276
new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
270277
if (!new_op)
271278
return -ENOMEM;
272279
new_op->upcall.req.getattr.refn = orangefs_inode->refn;
273-
new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
280+
/*
281+
* Size is the hardest attribute to get. The incremental cost of any
282+
* other attribute is essentially zero.
283+
*/
284+
if (request_mask & STATX_SIZE || new)
285+
new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_ALL_NOHINT;
286+
else
287+
new_op->upcall.req.getattr.mask =
288+
ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ORANGEFS_ATTR_SYS_SIZE;
274289

275290
ret = service_operation(new_op, __func__,
276291
get_interruptible_flag(inode));
@@ -291,25 +306,29 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
291306
case S_IFREG:
292307
inode->i_flags = orangefs_inode_flags(&new_op->
293308
downcall.resp.getattr.attributes);
294-
inode_size = (loff_t)new_op->
295-
downcall.resp.getattr.attributes.size;
296-
rounded_up_size =
297-
(inode_size + (4096 - (inode_size % 4096)));
298-
inode->i_size = inode_size;
299-
orangefs_inode->blksize =
300-
new_op->downcall.resp.getattr.attributes.blksize;
301-
spin_lock(&inode->i_lock);
302-
inode->i_bytes = inode_size;
303-
inode->i_blocks =
304-
(unsigned long)(rounded_up_size / 512);
305-
spin_unlock(&inode->i_lock);
309+
if (request_mask & STATX_SIZE || new) {
310+
inode_size = (loff_t)new_op->
311+
downcall.resp.getattr.attributes.size;
312+
rounded_up_size =
313+
(inode_size + (4096 - (inode_size % 4096)));
314+
inode->i_size = inode_size;
315+
orangefs_inode->blksize =
316+
new_op->downcall.resp.getattr.attributes.blksize;
317+
spin_lock(&inode->i_lock);
318+
inode->i_bytes = inode_size;
319+
inode->i_blocks =
320+
(unsigned long)(rounded_up_size / 512);
321+
spin_unlock(&inode->i_lock);
322+
}
306323
break;
307324
case S_IFDIR:
308-
inode->i_size = PAGE_SIZE;
309-
orangefs_inode->blksize = i_blocksize(inode);
310-
spin_lock(&inode->i_lock);
311-
inode_set_bytes(inode, inode->i_size);
312-
spin_unlock(&inode->i_lock);
325+
if (request_mask & STATX_SIZE || new) {
326+
inode->i_size = PAGE_SIZE;
327+
orangefs_inode->blksize = i_blocksize(inode);
328+
spin_lock(&inode->i_lock);
329+
inode_set_bytes(inode, inode->i_size);
330+
spin_unlock(&inode->i_lock);
331+
}
313332
set_nlink(inode, 1);
314333
break;
315334
case S_IFLNK:
@@ -349,6 +368,10 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
349368

350369
orangefs_inode->getattr_time = jiffies +
351370
orangefs_getattr_timeout_msecs*HZ/1000;
371+
if (request_mask & STATX_SIZE || new)
372+
orangefs_inode->getattr_mask = STATX_BASIC_STATS;
373+
else
374+
orangefs_inode->getattr_mask = STATX_BASIC_STATS & ~STATX_SIZE;
352375
ret = 0;
353376
out:
354377
op_release(new_op);

0 commit comments

Comments
 (0)