mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
gfs2 fixes
- Don't update inode timestamps for direct writes (performance regression fix). - Skip no-op quota records instead of panicing. - Fix a RCU race in gfs2_permission(). - Various other smaller fixes and cleanups all over the place. -----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEJZs3krPW0xkhLMTc1b+f6wMTZToFAmVKReAUHGFncnVlbmJh QHJlZGhhdC5jb20ACgkQ1b+f6wMTZTqZ0Q//RigZFdejtWEJ2GnrZfHCRxXXjF7A uXyK8PKv6xaHmF+I4PcEr/5yBkOxPhld0sBcsqdNUlvFbEl4AqLrXoSTMB2Fbq2h ycPTSPdGTFWjFJBIpN5F1LOQ0urxuS+fKkmxruaFwNywZqbPY0fYs7ZN5K76y0cL OKBcbOg5Q39Z+fqrxB0mf7WNIBfUxAsdelGQM3VK1ptNNxebmvBdNaWIhG7vWyWm MpWpPRwm906tOrMwhmy1oCCY6RrVC2naLlROOi58iodQ9sIF4MqmKOoejbbll6BH 1XMtOPQfO+IWWhq0/AX/xBL+nxuukko6V72Qg15e4sDhbla+vYrYEs4P+MZ5UU0u dM1MxnmV3xjKBw8KrnwMZL88ExuBhm6HLzKWlshJ4wye21Y3s2OKA2zCK2u3NBc3 GwYtNLBidoe8TjVD0ZeKeQJt2nZeKRrIWqQteaTHYpLHlRzCajEpmFS+ejEu59WC 8qw8MjTR2P6m8bPYNTbvxh6Lw4cE6ZHCj71nSPwrEDeU2QPQAmMKQg0bgTM7vpU7 HKl92Av20xhM+vyb/N670KcR/4yXEkUtbOzazyj/r/XB361luCFP9D9dRiNl7tOo TU0otksrkjJ7QrnVd3XUrA2N7iQEIeCVcx0k+KTGrJh7+yVzbUKaJ5W4Tsd+TVzB h/lfHAYS4FTd8nA= =YfOA -----END PGP SIGNATURE----- Merge tag 'gfs2-v6.6-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2 Pull gfs2 updates from Andreas Gruenbacher: - Don't update inode timestamps for direct writes (performance regression fix) - Skip no-op quota records instead of panicing - Fix a RCU race in gfs2_permission() - Various other smaller fixes and cleanups all over the place * tag 'gfs2-v6.6-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: (24 commits) gfs2: don't withdraw if init_threads() got interrupted gfs2: remove dead code in add_to_queue gfs2: Fix slab-use-after-free in gfs2_qd_dealloc gfs2: Silence "suspicious RCU usage in gfs2_permission" warning gfs2: fs: derive f_fsid from s_uuid gfs2: No longer use 'extern' in function declarations gfs2: Rename gfs2_lookup_{ simple => meta } gfs2: Convert gfs2_internal_read to folios gfs2: Convert stuffed_readpage to folios gfs2: Minor gfs2_write_jdata_batch PAGE_SIZE cleanup gfs2: Get rid of gfs2_alloc_blocks generation parameter gfs2: Add metapath_dibh helper gfs2: Clean up quota.c:print_message gfs2: Clean up gfs2_alloc_parms initializers gfs2: Two quota=account mode fixes gfs2: Stop using GFS2_BASIC_BLOCK and GFS2_BASIC_BLOCK_SHIFT gfs2: setattr_chown: Add missing initialization gfs2: fix an oops in gfs2_permission gfs2: ignore negated quota changes gfs2: Don't update inode timestamps for direct writes ...
This commit is contained in:
commit
1a0507d878
@ -11,9 +11,9 @@
|
||||
|
||||
#define GFS2_ACL_MAX_ENTRIES(sdp) ((300 << (sdp)->sd_sb.sb_bsize_shift) >> 12)
|
||||
|
||||
extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu);
|
||||
extern int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
|
||||
extern int gfs2_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
struct posix_acl *acl, int type);
|
||||
struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu);
|
||||
int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
|
||||
int gfs2_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
struct posix_acl *acl, int type);
|
||||
|
||||
#endif /* __ACL_DOT_H__ */
|
||||
|
@ -155,7 +155,7 @@ static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
|
||||
if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
|
||||
if (gfs2_assert_withdraw(sdp, ip->i_gl->gl_state == LM_ST_EXCLUSIVE))
|
||||
goto out;
|
||||
if (folio_test_checked(folio) || current->journal_info)
|
||||
goto out_ignore;
|
||||
@ -214,12 +214,12 @@ static int gfs2_write_jdata_batch(struct address_space *mapping,
|
||||
unsigned nrblocks;
|
||||
int i;
|
||||
int ret;
|
||||
int nr_pages = 0;
|
||||
size_t size = 0;
|
||||
int nr_folios = folio_batch_count(fbatch);
|
||||
|
||||
for (i = 0; i < nr_folios; i++)
|
||||
nr_pages += folio_nr_pages(fbatch->folios[i]);
|
||||
nrblocks = nr_pages * (PAGE_SIZE >> inode->i_blkbits);
|
||||
size += folio_size(fbatch->folios[i]);
|
||||
nrblocks = size >> inode->i_blkbits;
|
||||
|
||||
ret = gfs2_trans_begin(sdp, nrblocks, nrblocks);
|
||||
if (ret < 0)
|
||||
@ -403,27 +403,27 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
|
||||
}
|
||||
|
||||
/**
|
||||
* stuffed_readpage - Fill in a Linux page with stuffed file data
|
||||
* stuffed_readpage - Fill in a Linux folio with stuffed file data
|
||||
* @ip: the inode
|
||||
* @page: the page
|
||||
* @folio: the folio
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
|
||||
static int stuffed_readpage(struct gfs2_inode *ip, struct folio *folio)
|
||||
{
|
||||
struct buffer_head *dibh;
|
||||
u64 dsize = i_size_read(&ip->i_inode);
|
||||
void *kaddr;
|
||||
size_t i_size = i_size_read(&ip->i_inode);
|
||||
void *data;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Due to the order of unstuffing files and ->fault(), we can be
|
||||
* asked for a zero page in the case of a stuffed file being extended,
|
||||
* asked for a zero folio in the case of a stuffed file being extended,
|
||||
* so we need to supply one here. It doesn't happen often.
|
||||
*/
|
||||
if (unlikely(page->index)) {
|
||||
zero_user(page, 0, PAGE_SIZE);
|
||||
SetPageUptodate(page);
|
||||
if (unlikely(folio->index)) {
|
||||
folio_zero_range(folio, 0, folio_size(folio));
|
||||
folio_mark_uptodate(folio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -431,13 +431,11 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
kaddr = kmap_local_page(page);
|
||||
memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
|
||||
memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
|
||||
kunmap_local(kaddr);
|
||||
flush_dcache_page(page);
|
||||
data = dibh->b_data + sizeof(struct gfs2_dinode);
|
||||
memcpy_to_folio(folio, 0, data, i_size);
|
||||
folio_zero_range(folio, i_size, folio_size(folio) - i_size);
|
||||
brelse(dibh);
|
||||
SetPageUptodate(page);
|
||||
folio_mark_uptodate(folio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -458,7 +456,7 @@ static int gfs2_read_folio(struct file *file, struct folio *folio)
|
||||
(i_blocksize(inode) == PAGE_SIZE && !folio_buffers(folio))) {
|
||||
error = iomap_read_folio(folio, &gfs2_iomap_ops);
|
||||
} else if (gfs2_is_stuffed(ip)) {
|
||||
error = stuffed_readpage(ip, &folio->page);
|
||||
error = stuffed_readpage(ip, folio);
|
||||
folio_unlock(folio);
|
||||
} else {
|
||||
error = mpage_read_folio(folio, gfs2_block_map);
|
||||
@ -479,31 +477,29 @@ static int gfs2_read_folio(struct file *file, struct folio *folio)
|
||||
*
|
||||
*/
|
||||
|
||||
int gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos,
|
||||
unsigned size)
|
||||
ssize_t gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos,
|
||||
size_t size)
|
||||
{
|
||||
struct address_space *mapping = ip->i_inode.i_mapping;
|
||||
unsigned long index = *pos >> PAGE_SHIFT;
|
||||
unsigned offset = *pos & (PAGE_SIZE - 1);
|
||||
unsigned copied = 0;
|
||||
unsigned amt;
|
||||
struct page *page;
|
||||
size_t copied = 0;
|
||||
|
||||
do {
|
||||
page = read_cache_page(mapping, index, gfs2_read_folio, NULL);
|
||||
if (IS_ERR(page)) {
|
||||
if (PTR_ERR(page) == -EINTR)
|
||||
size_t offset, chunk;
|
||||
struct folio *folio;
|
||||
|
||||
folio = read_cache_folio(mapping, index, gfs2_read_folio, NULL);
|
||||
if (IS_ERR(folio)) {
|
||||
if (PTR_ERR(folio) == -EINTR)
|
||||
continue;
|
||||
return PTR_ERR(page);
|
||||
return PTR_ERR(folio);
|
||||
}
|
||||
amt = size - copied;
|
||||
if (offset + size > PAGE_SIZE)
|
||||
amt = PAGE_SIZE - offset;
|
||||
memcpy_from_page(buf + copied, page, offset, amt);
|
||||
put_page(page);
|
||||
copied += amt;
|
||||
index++;
|
||||
offset = 0;
|
||||
offset = *pos + copied - folio_pos(folio);
|
||||
chunk = min(size - copied, folio_size(folio) - offset);
|
||||
memcpy_from_folio(buf + copied, folio, offset, chunk);
|
||||
index = folio_next_index(folio);
|
||||
folio_put(folio);
|
||||
copied += chunk;
|
||||
} while(copied < size);
|
||||
(*pos) += size;
|
||||
return size;
|
||||
|
@ -8,8 +8,8 @@
|
||||
|
||||
#include "incore.h"
|
||||
|
||||
extern void adjust_fs_space(struct inode *inode);
|
||||
extern void gfs2_trans_add_databufs(struct gfs2_inode *ip, struct folio *folio,
|
||||
size_t from, size_t len);
|
||||
void adjust_fs_space(struct inode *inode);
|
||||
void gfs2_trans_add_databufs(struct gfs2_inode *ip, struct folio *folio,
|
||||
size_t from, size_t len);
|
||||
|
||||
#endif /* __AOPS_DOT_H__ */
|
||||
|
@ -104,7 +104,7 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio)
|
||||
and write it out to disk */
|
||||
|
||||
unsigned int n = 1;
|
||||
error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL);
|
||||
error = gfs2_alloc_blocks(ip, &block, &n, 0);
|
||||
if (error)
|
||||
goto out_brelse;
|
||||
if (isdir) {
|
||||
@ -315,6 +315,12 @@ static void gfs2_metapath_ra(struct gfs2_glock *gl, __be64 *start, __be64 *end)
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct buffer_head *
|
||||
metapath_dibh(struct metapath *mp)
|
||||
{
|
||||
return mp->mp_bh[0];
|
||||
}
|
||||
|
||||
static int __fillup_metapath(struct gfs2_inode *ip, struct metapath *mp,
|
||||
unsigned int x, unsigned int h)
|
||||
{
|
||||
@ -413,13 +419,12 @@ static void release_metapath(struct metapath *mp)
|
||||
* gfs2_extent_length - Returns length of an extent of blocks
|
||||
* @bh: The metadata block
|
||||
* @ptr: Current position in @bh
|
||||
* @limit: Max extent length to return
|
||||
* @eob: Set to 1 if we hit "end of block"
|
||||
*
|
||||
* Returns: The length of the extent (minimum of one block)
|
||||
*/
|
||||
|
||||
static inline unsigned int gfs2_extent_length(struct buffer_head *bh, __be64 *ptr, size_t limit, int *eob)
|
||||
static inline unsigned int gfs2_extent_length(struct buffer_head *bh, __be64 *ptr, int *eob)
|
||||
{
|
||||
const __be64 *end = (__be64 *)(bh->b_data + bh->b_size);
|
||||
const __be64 *first = ptr;
|
||||
@ -658,7 +663,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct buffer_head *dibh = mp->mp_bh[0];
|
||||
struct buffer_head *dibh = metapath_dibh(mp);
|
||||
u64 bn;
|
||||
unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0;
|
||||
size_t dblks = iomap->length >> inode->i_blkbits;
|
||||
@ -700,7 +705,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
|
||||
i = mp->mp_aheight;
|
||||
do {
|
||||
n = blks - alloced;
|
||||
ret = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
|
||||
ret = gfs2_alloc_blocks(ip, &bn, &n, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
alloced += n;
|
||||
@ -911,7 +916,7 @@ unstuff:
|
||||
goto do_alloc;
|
||||
|
||||
bh = mp->mp_bh[ip->i_height - 1];
|
||||
len = gfs2_extent_length(bh, ptr, len, &eob);
|
||||
len = gfs2_extent_length(bh, ptr, &eob);
|
||||
|
||||
iomap->addr = be64_to_cpu(*ptr) << inode->i_blkbits;
|
||||
iomap->length = len << inode->i_blkbits;
|
||||
|
@ -46,24 +46,24 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip,
|
||||
extern const struct iomap_ops gfs2_iomap_ops;
|
||||
extern const struct iomap_writeback_ops gfs2_writeback_ops;
|
||||
|
||||
extern int gfs2_unstuff_dinode(struct gfs2_inode *ip);
|
||||
extern int gfs2_block_map(struct inode *inode, sector_t lblock,
|
||||
struct buffer_head *bh, int create);
|
||||
extern int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
|
||||
struct iomap *iomap);
|
||||
extern int gfs2_iomap_alloc(struct inode *inode, loff_t pos, loff_t length,
|
||||
struct iomap *iomap);
|
||||
extern int gfs2_get_extent(struct inode *inode, u64 lblock, u64 *dblock,
|
||||
unsigned int *extlen);
|
||||
extern int gfs2_alloc_extent(struct inode *inode, u64 lblock, u64 *dblock,
|
||||
unsigned *extlen, bool *new);
|
||||
extern int gfs2_setattr_size(struct inode *inode, u64 size);
|
||||
extern int gfs2_truncatei_resume(struct gfs2_inode *ip);
|
||||
extern int gfs2_file_dealloc(struct gfs2_inode *ip);
|
||||
extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
unsigned int len);
|
||||
extern int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd);
|
||||
extern void gfs2_free_journal_extents(struct gfs2_jdesc *jd);
|
||||
extern int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length);
|
||||
int gfs2_unstuff_dinode(struct gfs2_inode *ip);
|
||||
int gfs2_block_map(struct inode *inode, sector_t lblock,
|
||||
struct buffer_head *bh, int create);
|
||||
int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
|
||||
struct iomap *iomap);
|
||||
int gfs2_iomap_alloc(struct inode *inode, loff_t pos, loff_t length,
|
||||
struct iomap *iomap);
|
||||
int gfs2_get_extent(struct inode *inode, u64 lblock, u64 *dblock,
|
||||
unsigned int *extlen);
|
||||
int gfs2_alloc_extent(struct inode *inode, u64 lblock, u64 *dblock,
|
||||
unsigned *extlen, bool *new);
|
||||
int gfs2_setattr_size(struct inode *inode, u64 size);
|
||||
int gfs2_truncatei_resume(struct gfs2_inode *ip);
|
||||
int gfs2_file_dealloc(struct gfs2_inode *ip);
|
||||
int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
|
||||
unsigned int len);
|
||||
int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd);
|
||||
void gfs2_free_journal_extents(struct gfs2_jdesc *jd);
|
||||
int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length);
|
||||
|
||||
#endif /* __BMAP_DOT_H__ */
|
||||
|
@ -868,7 +868,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
|
||||
struct gfs2_dirent *dent;
|
||||
struct timespec64 tv = current_time(inode);
|
||||
|
||||
error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
|
||||
error = gfs2_alloc_blocks(ip, &bn, &n, 0);
|
||||
if (error)
|
||||
return NULL;
|
||||
bh = gfs2_meta_new(ip->i_gl, bn);
|
||||
|
@ -23,32 +23,32 @@ struct gfs2_diradd {
|
||||
int save_loc;
|
||||
};
|
||||
|
||||
extern struct inode *gfs2_dir_search(struct inode *dir,
|
||||
const struct qstr *filename,
|
||||
bool fail_on_exist);
|
||||
extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip);
|
||||
extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip, struct gfs2_diradd *da);
|
||||
struct inode *gfs2_dir_search(struct inode *dir,
|
||||
const struct qstr *filename,
|
||||
bool fail_on_exist);
|
||||
int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip);
|
||||
int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
|
||||
const struct gfs2_inode *ip, struct gfs2_diradd *da);
|
||||
static inline void gfs2_dir_no_add(struct gfs2_diradd *da)
|
||||
{
|
||||
brelse(da->bh);
|
||||
da->bh = NULL;
|
||||
}
|
||||
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
|
||||
extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
|
||||
struct file_ra_state *f_ra);
|
||||
extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
|
||||
const struct gfs2_inode *nip, unsigned int new_type);
|
||||
int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
|
||||
int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
|
||||
struct file_ra_state *f_ra);
|
||||
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
|
||||
const struct gfs2_inode *nip, unsigned int new_type);
|
||||
|
||||
extern int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
|
||||
int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
|
||||
|
||||
extern int gfs2_diradd_alloc_required(struct inode *dir,
|
||||
const struct qstr *filename,
|
||||
struct gfs2_diradd *da);
|
||||
extern int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
|
||||
struct buffer_head **bhp);
|
||||
extern void gfs2_dir_hash_inval(struct gfs2_inode *ip);
|
||||
int gfs2_diradd_alloc_required(struct inode *dir,
|
||||
const struct qstr *filename,
|
||||
struct gfs2_diradd *da);
|
||||
int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
|
||||
struct buffer_head **bhp);
|
||||
void gfs2_dir_hash_inval(struct gfs2_inode *ip);
|
||||
|
||||
static inline u32 gfs2_disk_hash(const char *data, int len)
|
||||
{
|
||||
|
@ -418,7 +418,7 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
|
||||
struct inode *inode = file_inode(vmf->vma->vm_file);
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct gfs2_alloc_parms ap = { .aflags = 0, };
|
||||
struct gfs2_alloc_parms ap = {};
|
||||
u64 offset = page_offset(page);
|
||||
unsigned int data_blocks, ind_blocks, rblocks;
|
||||
vm_fault_t ret = VM_FAULT_LOCKED;
|
||||
@ -1120,14 +1120,16 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
ret = file_update_time(file);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
if (iocb->ki_flags & IOCB_DIRECT) {
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
ssize_t buffered, ret2;
|
||||
|
||||
/*
|
||||
* Note that under direct I/O, we don't allow and inode
|
||||
* timestamp updates, so we're not calling file_update_time()
|
||||
* here.
|
||||
*/
|
||||
|
||||
ret = gfs2_file_direct_write(iocb, from, &gh);
|
||||
if (ret < 0 || !iov_iter_count(from))
|
||||
goto out_unlock;
|
||||
@ -1154,6 +1156,10 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (!ret || ret2 > 0)
|
||||
ret += ret2;
|
||||
} else {
|
||||
ret = file_update_time(file);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
ret = gfs2_file_buffered_write(iocb, from, &gh);
|
||||
if (likely(ret > 0))
|
||||
ret = generic_write_sync(iocb, ret);
|
||||
@ -1245,7 +1251,7 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
|
||||
struct inode *inode = file_inode(file);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_alloc_parms ap = { .aflags = 0, };
|
||||
struct gfs2_alloc_parms ap = {};
|
||||
unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
|
||||
loff_t bytes, max_bytes, max_blks;
|
||||
int error;
|
||||
|
@ -1524,7 +1524,6 @@ fail:
|
||||
return;
|
||||
}
|
||||
list_add_tail(&gh->gh_list, insert_pt);
|
||||
gh = list_first_entry(&gl->gl_holders, struct gfs2_holder, gh_list);
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
if (sdp->sd_lockstruct.ls_ops->lm_cancel)
|
||||
sdp->sd_lockstruct.ls_ops->lm_cancel(gl);
|
||||
|
113
fs/gfs2/glock.h
113
fs/gfs2/glock.h
@ -156,21 +156,6 @@ out:
|
||||
return gh;
|
||||
}
|
||||
|
||||
static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl)
|
||||
{
|
||||
return gl->gl_state == LM_ST_EXCLUSIVE;
|
||||
}
|
||||
|
||||
static inline int gfs2_glock_is_held_dfrd(struct gfs2_glock *gl)
|
||||
{
|
||||
return gl->gl_state == LM_ST_DEFERRED;
|
||||
}
|
||||
|
||||
static inline int gfs2_glock_is_held_shrd(struct gfs2_glock *gl)
|
||||
{
|
||||
return gl->gl_state == LM_ST_SHARED;
|
||||
}
|
||||
|
||||
static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
|
||||
{
|
||||
if (gl->gl_ops->go_flags & GLOF_ASPACE) {
|
||||
@ -181,40 +166,40 @@ static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
|
||||
const struct gfs2_glock_operations *glops,
|
||||
int create, struct gfs2_glock **glp);
|
||||
extern struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl);
|
||||
extern void gfs2_glock_put(struct gfs2_glock *gl);
|
||||
extern void gfs2_glock_queue_put(struct gfs2_glock *gl);
|
||||
int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
|
||||
const struct gfs2_glock_operations *glops,
|
||||
int create, struct gfs2_glock **glp);
|
||||
struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl);
|
||||
void gfs2_glock_put(struct gfs2_glock *gl);
|
||||
void gfs2_glock_queue_put(struct gfs2_glock *gl);
|
||||
|
||||
extern void __gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
|
||||
u16 flags, struct gfs2_holder *gh,
|
||||
unsigned long ip);
|
||||
void __gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
|
||||
u16 flags, struct gfs2_holder *gh,
|
||||
unsigned long ip);
|
||||
static inline void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
|
||||
u16 flags, struct gfs2_holder *gh) {
|
||||
__gfs2_holder_init(gl, state, flags, gh, _RET_IP_);
|
||||
}
|
||||
|
||||
extern void gfs2_holder_reinit(unsigned int state, u16 flags,
|
||||
struct gfs2_holder *gh);
|
||||
extern void gfs2_holder_uninit(struct gfs2_holder *gh);
|
||||
extern int gfs2_glock_nq(struct gfs2_holder *gh);
|
||||
extern int gfs2_glock_poll(struct gfs2_holder *gh);
|
||||
extern int gfs2_instantiate(struct gfs2_holder *gh);
|
||||
extern int gfs2_glock_holder_ready(struct gfs2_holder *gh);
|
||||
extern int gfs2_glock_wait(struct gfs2_holder *gh);
|
||||
extern int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs);
|
||||
extern void gfs2_glock_dq(struct gfs2_holder *gh);
|
||||
extern void gfs2_glock_dq_wait(struct gfs2_holder *gh);
|
||||
extern void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
|
||||
extern int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number,
|
||||
const struct gfs2_glock_operations *glops,
|
||||
unsigned int state, u16 flags,
|
||||
struct gfs2_holder *gh);
|
||||
extern int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
|
||||
extern void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
|
||||
extern void gfs2_dump_glock(struct seq_file *seq, struct gfs2_glock *gl,
|
||||
void gfs2_holder_reinit(unsigned int state, u16 flags,
|
||||
struct gfs2_holder *gh);
|
||||
void gfs2_holder_uninit(struct gfs2_holder *gh);
|
||||
int gfs2_glock_nq(struct gfs2_holder *gh);
|
||||
int gfs2_glock_poll(struct gfs2_holder *gh);
|
||||
int gfs2_instantiate(struct gfs2_holder *gh);
|
||||
int gfs2_glock_holder_ready(struct gfs2_holder *gh);
|
||||
int gfs2_glock_wait(struct gfs2_holder *gh);
|
||||
int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs);
|
||||
void gfs2_glock_dq(struct gfs2_holder *gh);
|
||||
void gfs2_glock_dq_wait(struct gfs2_holder *gh);
|
||||
void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
|
||||
int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number,
|
||||
const struct gfs2_glock_operations *glops,
|
||||
unsigned int state, u16 flags,
|
||||
struct gfs2_holder *gh);
|
||||
int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
|
||||
void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
|
||||
void gfs2_dump_glock(struct seq_file *seq, struct gfs2_glock *gl,
|
||||
bool fsid);
|
||||
#define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { \
|
||||
gfs2_dump_glock(NULL, gl, true); \
|
||||
@ -228,7 +213,7 @@ extern void gfs2_dump_glock(struct seq_file *seq, struct gfs2_glock *gl,
|
||||
gfs2_assert_withdraw((gl)->gl_name.ln_sbd, (x)); } } \
|
||||
while (0)
|
||||
|
||||
extern __printf(2, 3)
|
||||
__printf(2, 3)
|
||||
void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
@ -256,27 +241,27 @@ static inline int gfs2_glock_nq_init(struct gfs2_glock *gl,
|
||||
return error;
|
||||
}
|
||||
|
||||
extern void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state);
|
||||
extern void gfs2_glock_complete(struct gfs2_glock *gl, int ret);
|
||||
extern bool gfs2_queue_try_to_evict(struct gfs2_glock *gl);
|
||||
extern void gfs2_cancel_delete_work(struct gfs2_glock *gl);
|
||||
extern void gfs2_flush_delete_work(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_gl_dq_holders(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_glock_thaw(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_glock_add_to_lru(struct gfs2_glock *gl);
|
||||
extern void gfs2_glock_free(struct gfs2_glock *gl);
|
||||
void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state);
|
||||
void gfs2_glock_complete(struct gfs2_glock *gl, int ret);
|
||||
bool gfs2_queue_try_to_evict(struct gfs2_glock *gl);
|
||||
void gfs2_cancel_delete_work(struct gfs2_glock *gl);
|
||||
void gfs2_flush_delete_work(struct gfs2_sbd *sdp);
|
||||
void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
|
||||
void gfs2_gl_dq_holders(struct gfs2_sbd *sdp);
|
||||
void gfs2_glock_thaw(struct gfs2_sbd *sdp);
|
||||
void gfs2_glock_add_to_lru(struct gfs2_glock *gl);
|
||||
void gfs2_glock_free(struct gfs2_glock *gl);
|
||||
|
||||
extern int __init gfs2_glock_init(void);
|
||||
extern void gfs2_glock_exit(void);
|
||||
int __init gfs2_glock_init(void);
|
||||
void gfs2_glock_exit(void);
|
||||
|
||||
extern void gfs2_create_debugfs_file(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_register_debugfs(void);
|
||||
extern void gfs2_unregister_debugfs(void);
|
||||
void gfs2_create_debugfs_file(struct gfs2_sbd *sdp);
|
||||
void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp);
|
||||
void gfs2_register_debugfs(void);
|
||||
void gfs2_unregister_debugfs(void);
|
||||
|
||||
extern void glock_set_object(struct gfs2_glock *gl, void *object);
|
||||
extern void glock_clear_object(struct gfs2_glock *gl, void *object);
|
||||
void glock_set_object(struct gfs2_glock *gl, void *object);
|
||||
void glock_clear_object(struct gfs2_glock *gl, void *object);
|
||||
|
||||
extern const struct lm_lockops gfs2_dlm_ops;
|
||||
|
||||
@ -295,7 +280,7 @@ static inline bool gfs2_holder_queued(struct gfs2_holder *gh)
|
||||
return !list_empty(&gh->gh_list);
|
||||
}
|
||||
|
||||
extern void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation);
|
||||
extern bool gfs2_inode_already_deleted(struct gfs2_glock *gl, u64 generation);
|
||||
void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation);
|
||||
bool gfs2_inode_already_deleted(struct gfs2_glock *gl, u64 generation);
|
||||
|
||||
#endif /* __GLOCK_DOT_H__ */
|
||||
|
@ -614,18 +614,6 @@ static int freeze_go_xmote_bh(struct gfs2_glock *gl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* freeze_go_demote_ok
|
||||
* @gl: the glock
|
||||
*
|
||||
* Always returns 0
|
||||
*/
|
||||
|
||||
static int freeze_go_demote_ok(const struct gfs2_glock *gl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iopen_go_callback - schedule the dcache entry for the inode to be deleted
|
||||
* @gl: the glock
|
||||
@ -745,7 +733,6 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
|
||||
|
||||
const struct gfs2_glock_operations gfs2_freeze_glops = {
|
||||
.go_xmote_bh = freeze_go_xmote_bh,
|
||||
.go_demote_ok = freeze_go_demote_ok,
|
||||
.go_callback = freeze_go_callback,
|
||||
.go_type = LM_TYPE_NONDISK,
|
||||
.go_flags = GLOF_NONDISK,
|
||||
|
@ -22,7 +22,7 @@ extern const struct gfs2_glock_operations gfs2_quota_glops;
|
||||
extern const struct gfs2_glock_operations gfs2_journal_glops;
|
||||
extern const struct gfs2_glock_operations *gfs2_glops_list[];
|
||||
|
||||
extern int gfs2_inode_metasync(struct gfs2_glock *gl);
|
||||
extern void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync);
|
||||
int gfs2_inode_metasync(struct gfs2_glock *gl);
|
||||
void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync);
|
||||
|
||||
#endif /* __GLOPS_DOT_H__ */
|
||||
|
@ -863,7 +863,7 @@ static inline void gfs2_sbstats_inc(const struct gfs2_glock *gl, int which)
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
extern struct gfs2_rgrpd *gfs2_glock2rgrp(struct gfs2_glock *gl);
|
||||
struct gfs2_rgrpd *gfs2_glock2rgrp(struct gfs2_glock *gl);
|
||||
|
||||
static inline unsigned gfs2_max_stuffed_size(const struct gfs2_inode *ip)
|
||||
{
|
||||
|
@ -266,17 +266,18 @@ fail_iput:
|
||||
}
|
||||
|
||||
|
||||
struct inode *gfs2_lookup_simple(struct inode *dip, const char *name)
|
||||
/**
|
||||
* gfs2_lookup_meta - Look up an inode in a metadata directory
|
||||
* @dip: The directory
|
||||
* @name: The name of the inode
|
||||
*/
|
||||
struct inode *gfs2_lookup_meta(struct inode *dip, const char *name)
|
||||
{
|
||||
struct qstr qstr;
|
||||
struct inode *inode;
|
||||
|
||||
gfs2_str2qstr(&qstr, name);
|
||||
inode = gfs2_lookupi(dip, &qstr, 1);
|
||||
/* gfs2_lookupi has inconsistent callers: vfs
|
||||
* related routines expect NULL for no entry found,
|
||||
* gfs2_lookup_simple callers expect ENOENT
|
||||
* and do not check for NULL.
|
||||
*/
|
||||
if (IS_ERR_OR_NULL(inode))
|
||||
return inode ? inode : ERR_PTR(-ENOENT);
|
||||
|
||||
@ -418,7 +419,7 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks)
|
||||
if (error)
|
||||
goto out_ipreserv;
|
||||
|
||||
error = gfs2_alloc_blocks(ip, &ip->i_no_addr, dblocks, 1, &ip->i_generation);
|
||||
error = gfs2_alloc_blocks(ip, &ip->i_no_addr, dblocks, 1);
|
||||
if (error)
|
||||
goto out_trans_end;
|
||||
|
||||
@ -1867,16 +1868,24 @@ out:
|
||||
int gfs2_permission(struct mnt_idmap *idmap, struct inode *inode,
|
||||
int mask)
|
||||
{
|
||||
int may_not_block = mask & MAY_NOT_BLOCK;
|
||||
struct gfs2_inode *ip;
|
||||
struct gfs2_holder i_gh;
|
||||
struct gfs2_glock *gl;
|
||||
int error;
|
||||
|
||||
gfs2_holder_mark_uninitialized(&i_gh);
|
||||
ip = GFS2_I(inode);
|
||||
if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
|
||||
if (mask & MAY_NOT_BLOCK)
|
||||
gl = rcu_dereference_check(ip->i_gl, !may_not_block);
|
||||
if (unlikely(!gl)) {
|
||||
/* inode is getting torn down, must be RCU mode */
|
||||
WARN_ON_ONCE(!may_not_block);
|
||||
return -ECHILD;
|
||||
}
|
||||
if (gfs2_glock_is_locked_by_me(gl) == NULL) {
|
||||
if (may_not_block)
|
||||
return -ECHILD;
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
|
||||
error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
@ -1921,7 +1930,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
|
||||
kuid_t ouid, nuid;
|
||||
kgid_t ogid, ngid;
|
||||
int error;
|
||||
struct gfs2_alloc_parms ap;
|
||||
struct gfs2_alloc_parms ap = {};
|
||||
|
||||
ouid = inode->i_uid;
|
||||
ogid = inode->i_gid;
|
||||
@ -2154,7 +2163,7 @@ static int gfs2_update_time(struct inode *inode, int flags)
|
||||
int error;
|
||||
|
||||
gh = gfs2_glock_is_locked_by_me(gl);
|
||||
if (gh && !gfs2_glock_is_held_excl(gl)) {
|
||||
if (gh && gl->gl_state != LM_ST_EXCLUSIVE) {
|
||||
gfs2_glock_dq(gh);
|
||||
gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, gh);
|
||||
error = gfs2_glock_nq(gh);
|
||||
|
@ -13,9 +13,9 @@
|
||||
#include "util.h"
|
||||
|
||||
bool gfs2_release_folio(struct folio *folio, gfp_t gfp_mask);
|
||||
extern int gfs2_internal_read(struct gfs2_inode *ip,
|
||||
char *buf, loff_t *pos, unsigned size);
|
||||
extern void gfs2_set_aops(struct inode *inode);
|
||||
ssize_t gfs2_internal_read(struct gfs2_inode *ip,
|
||||
char *buf, loff_t *pos, size_t size);
|
||||
void gfs2_set_aops(struct inode *inode);
|
||||
|
||||
static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
|
||||
{
|
||||
@ -44,19 +44,17 @@ static inline int gfs2_is_dir(const struct gfs2_inode *ip)
|
||||
|
||||
static inline void gfs2_set_inode_blocks(struct inode *inode, u64 blocks)
|
||||
{
|
||||
inode->i_blocks = blocks <<
|
||||
(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
|
||||
inode->i_blocks = blocks << (inode->i_blkbits - 9);
|
||||
}
|
||||
|
||||
static inline u64 gfs2_get_inode_blocks(const struct inode *inode)
|
||||
{
|
||||
return inode->i_blocks >>
|
||||
(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
|
||||
return inode->i_blocks >> (inode->i_blkbits - 9);
|
||||
}
|
||||
|
||||
static inline void gfs2_add_inode_blocks(struct inode *inode, s64 change)
|
||||
{
|
||||
change <<= inode->i_blkbits - GFS2_BASIC_BLOCK_SHIFT;
|
||||
change <<= inode->i_blkbits - 9;
|
||||
gfs2_assert(GFS2_SB(inode), (change >= 0 || inode->i_blocks >= -change));
|
||||
inode->i_blocks += change;
|
||||
}
|
||||
@ -88,33 +86,33 @@ err:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
|
||||
u64 no_addr, u64 no_formal_ino,
|
||||
unsigned int blktype);
|
||||
extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
|
||||
u64 no_formal_ino,
|
||||
unsigned int blktype);
|
||||
struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
|
||||
u64 no_addr, u64 no_formal_ino,
|
||||
unsigned int blktype);
|
||||
struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
|
||||
u64 no_formal_ino,
|
||||
unsigned int blktype);
|
||||
|
||||
extern int gfs2_inode_refresh(struct gfs2_inode *ip);
|
||||
int gfs2_inode_refresh(struct gfs2_inode *ip);
|
||||
|
||||
extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
|
||||
int is_root);
|
||||
extern int gfs2_permission(struct mnt_idmap *idmap,
|
||||
struct inode *inode, int mask);
|
||||
extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
|
||||
extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
|
||||
extern int gfs2_open_common(struct inode *inode, struct file *file);
|
||||
extern loff_t gfs2_seek_data(struct file *file, loff_t offset);
|
||||
extern loff_t gfs2_seek_hole(struct file *file, loff_t offset);
|
||||
struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
|
||||
int is_root);
|
||||
int gfs2_permission(struct mnt_idmap *idmap,
|
||||
struct inode *inode, int mask);
|
||||
struct inode *gfs2_lookup_meta(struct inode *dip, const char *name);
|
||||
void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
|
||||
int gfs2_open_common(struct inode *inode, struct file *file);
|
||||
loff_t gfs2_seek_data(struct file *file, loff_t offset);
|
||||
loff_t gfs2_seek_hole(struct file *file, loff_t offset);
|
||||
|
||||
extern const struct file_operations gfs2_file_fops_nolock;
|
||||
extern const struct file_operations gfs2_dir_fops_nolock;
|
||||
|
||||
extern int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa);
|
||||
extern int gfs2_fileattr_set(struct mnt_idmap *idmap,
|
||||
struct dentry *dentry, struct fileattr *fa);
|
||||
extern void gfs2_set_inode_flags(struct inode *inode);
|
||||
|
||||
int gfs2_fileattr_get(struct dentry *dentry, struct fileattr *fa);
|
||||
int gfs2_fileattr_set(struct mnt_idmap *idmap,
|
||||
struct dentry *dentry, struct fileattr *fa);
|
||||
void gfs2_set_inode_flags(struct inode *inode);
|
||||
|
||||
#ifdef CONFIG_GFS2_FS_LOCKING_DLM
|
||||
extern const struct file_operations gfs2_file_fops;
|
||||
extern const struct file_operations gfs2_dir_fops;
|
||||
|
@ -70,29 +70,29 @@ static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip)
|
||||
}
|
||||
}
|
||||
|
||||
extern void gfs2_ordered_del_inode(struct gfs2_inode *ip);
|
||||
extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct);
|
||||
extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
|
||||
extern bool gfs2_log_is_empty(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_log_release_revokes(struct gfs2_sbd *sdp, unsigned int revokes);
|
||||
extern void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
|
||||
extern bool gfs2_log_try_reserve(struct gfs2_sbd *sdp, struct gfs2_trans *tr,
|
||||
unsigned int *extra_revokes);
|
||||
extern void gfs2_log_reserve(struct gfs2_sbd *sdp, struct gfs2_trans *tr,
|
||||
unsigned int *extra_revokes);
|
||||
extern void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
u64 seq, u32 tail, u32 lblock, u32 flags,
|
||||
blk_opf_t op_flags);
|
||||
extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
|
||||
u32 type);
|
||||
extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
|
||||
extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc);
|
||||
extern void log_flush_wait(struct gfs2_sbd *sdp);
|
||||
void gfs2_ordered_del_inode(struct gfs2_inode *ip);
|
||||
unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct);
|
||||
void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
|
||||
bool gfs2_log_is_empty(struct gfs2_sbd *sdp);
|
||||
void gfs2_log_release_revokes(struct gfs2_sbd *sdp, unsigned int revokes);
|
||||
void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks);
|
||||
bool gfs2_log_try_reserve(struct gfs2_sbd *sdp, struct gfs2_trans *tr,
|
||||
unsigned int *extra_revokes);
|
||||
void gfs2_log_reserve(struct gfs2_sbd *sdp, struct gfs2_trans *tr,
|
||||
unsigned int *extra_revokes);
|
||||
void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
u64 seq, u32 tail, u32 lblock, u32 flags,
|
||||
blk_opf_t op_flags);
|
||||
void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
|
||||
u32 type);
|
||||
void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
|
||||
void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc);
|
||||
void log_flush_wait(struct gfs2_sbd *sdp);
|
||||
|
||||
extern int gfs2_logd(void *data);
|
||||
extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
|
||||
extern void gfs2_glock_remove_revoke(struct gfs2_glock *gl);
|
||||
extern void gfs2_flush_revokes(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_ail_drain(struct gfs2_sbd *sdp);
|
||||
int gfs2_logd(void *data);
|
||||
void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
|
||||
void gfs2_glock_remove_revoke(struct gfs2_glock *gl);
|
||||
void gfs2_flush_revokes(struct gfs2_sbd *sdp);
|
||||
void gfs2_ail_drain(struct gfs2_sbd *sdp);
|
||||
|
||||
#endif /* __LOG_DOT_H__ */
|
||||
|
@ -11,16 +11,18 @@
|
||||
#include "incore.h"
|
||||
|
||||
extern const struct gfs2_log_operations *gfs2_log_ops[];
|
||||
extern void gfs2_log_incr_head(struct gfs2_sbd *sdp);
|
||||
extern u64 gfs2_log_bmap(struct gfs2_jdesc *jd, unsigned int lbn);
|
||||
extern void gfs2_log_write(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
struct page *page, unsigned size, unsigned offset,
|
||||
u64 blkno);
|
||||
extern void gfs2_log_submit_bio(struct bio **biop, blk_opf_t opf);
|
||||
extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
|
||||
extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
|
||||
struct gfs2_log_header_host *head, bool keep_cache);
|
||||
extern void gfs2_drain_revokes(struct gfs2_sbd *sdp);
|
||||
|
||||
void gfs2_log_incr_head(struct gfs2_sbd *sdp);
|
||||
u64 gfs2_log_bmap(struct gfs2_jdesc *jd, unsigned int lbn);
|
||||
void gfs2_log_write(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
struct page *page, unsigned size, unsigned offset,
|
||||
u64 blkno);
|
||||
void gfs2_log_submit_bio(struct bio **biop, blk_opf_t opf);
|
||||
void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
|
||||
int gfs2_find_jhead(struct gfs2_jdesc *jd,
|
||||
struct gfs2_log_header_host *head, bool keep_cache);
|
||||
void gfs2_drain_revokes(struct gfs2_sbd *sdp);
|
||||
|
||||
static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
|
||||
{
|
||||
return sdp->sd_ldptrs;
|
||||
|
@ -50,21 +50,21 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
|
||||
return inode->i_sb->s_fs_info;
|
||||
}
|
||||
|
||||
extern struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
|
||||
extern int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
|
||||
int rahead, struct buffer_head **bhp);
|
||||
extern int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
|
||||
extern struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno,
|
||||
int create);
|
||||
struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
|
||||
int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
|
||||
int rahead, struct buffer_head **bhp);
|
||||
int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
|
||||
struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno,
|
||||
int create);
|
||||
enum {
|
||||
REMOVE_JDATA = 0,
|
||||
REMOVE_META = 1,
|
||||
};
|
||||
|
||||
extern void gfs2_remove_from_journal(struct buffer_head *bh, int meta);
|
||||
extern void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
|
||||
extern int gfs2_meta_buffer(struct gfs2_inode *ip, u32 mtype, u64 num,
|
||||
struct buffer_head **bhp);
|
||||
void gfs2_remove_from_journal(struct buffer_head *bh, int meta);
|
||||
void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen);
|
||||
int gfs2_meta_buffer(struct gfs2_inode *ip, u32 mtype, u64 num,
|
||||
struct buffer_head **bhp);
|
||||
|
||||
static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
|
||||
struct buffer_head **bhp)
|
||||
|
@ -292,8 +292,7 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent)
|
||||
return error;
|
||||
}
|
||||
|
||||
sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift -
|
||||
GFS2_BASIC_BLOCK_SHIFT;
|
||||
sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - 9;
|
||||
sdp->sd_fsb2bb = BIT(sdp->sd_fsb2bb_shift);
|
||||
sdp->sd_diptrs = (sdp->sd_sb.sb_bsize -
|
||||
sizeof(struct gfs2_dinode)) / sizeof(u64);
|
||||
@ -648,7 +647,7 @@ static int init_statfs(struct gfs2_sbd *sdp)
|
||||
struct gfs2_jdesc *jd;
|
||||
struct gfs2_inode *ip;
|
||||
|
||||
sdp->sd_statfs_inode = gfs2_lookup_simple(master, "statfs");
|
||||
sdp->sd_statfs_inode = gfs2_lookup_meta(master, "statfs");
|
||||
if (IS_ERR(sdp->sd_statfs_inode)) {
|
||||
error = PTR_ERR(sdp->sd_statfs_inode);
|
||||
fs_err(sdp, "can't read in statfs inode: %d\n", error);
|
||||
@ -657,7 +656,7 @@ static int init_statfs(struct gfs2_sbd *sdp)
|
||||
if (sdp->sd_args.ar_spectator)
|
||||
goto out;
|
||||
|
||||
pn = gfs2_lookup_simple(master, "per_node");
|
||||
pn = gfs2_lookup_meta(master, "per_node");
|
||||
if (IS_ERR(pn)) {
|
||||
error = PTR_ERR(pn);
|
||||
fs_err(sdp, "can't find per_node directory: %d\n", error);
|
||||
@ -674,7 +673,7 @@ static int init_statfs(struct gfs2_sbd *sdp)
|
||||
goto free_local;
|
||||
}
|
||||
sprintf(buf, "statfs_change%u", jd->jd_jid);
|
||||
lsi->si_sc_inode = gfs2_lookup_simple(pn, buf);
|
||||
lsi->si_sc_inode = gfs2_lookup_meta(pn, buf);
|
||||
if (IS_ERR(lsi->si_sc_inode)) {
|
||||
error = PTR_ERR(lsi->si_sc_inode);
|
||||
fs_err(sdp, "can't find local \"sc\" file#%u: %d\n",
|
||||
@ -739,7 +738,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
||||
if (undo)
|
||||
goto fail_statfs;
|
||||
|
||||
sdp->sd_jindex = gfs2_lookup_simple(master, "jindex");
|
||||
sdp->sd_jindex = gfs2_lookup_meta(master, "jindex");
|
||||
if (IS_ERR(sdp->sd_jindex)) {
|
||||
fs_err(sdp, "can't lookup journal index: %d\n", error);
|
||||
return PTR_ERR(sdp->sd_jindex);
|
||||
@ -888,7 +887,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
|
||||
goto fail;
|
||||
|
||||
/* Read in the resource index inode */
|
||||
sdp->sd_rindex = gfs2_lookup_simple(master, "rindex");
|
||||
sdp->sd_rindex = gfs2_lookup_meta(master, "rindex");
|
||||
if (IS_ERR(sdp->sd_rindex)) {
|
||||
error = PTR_ERR(sdp->sd_rindex);
|
||||
fs_err(sdp, "can't get resource index inode: %d\n", error);
|
||||
@ -897,7 +896,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
|
||||
sdp->sd_rindex_uptodate = 0;
|
||||
|
||||
/* Read in the quota inode */
|
||||
sdp->sd_quota_inode = gfs2_lookup_simple(master, "quota");
|
||||
sdp->sd_quota_inode = gfs2_lookup_meta(master, "quota");
|
||||
if (IS_ERR(sdp->sd_quota_inode)) {
|
||||
error = PTR_ERR(sdp->sd_quota_inode);
|
||||
fs_err(sdp, "can't get quota file inode: %d\n", error);
|
||||
@ -941,7 +940,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
|
||||
if (undo)
|
||||
goto fail_qc_gh;
|
||||
|
||||
pn = gfs2_lookup_simple(master, "per_node");
|
||||
pn = gfs2_lookup_meta(master, "per_node");
|
||||
if (IS_ERR(pn)) {
|
||||
error = PTR_ERR(pn);
|
||||
fs_err(sdp, "can't find per_node directory: %d\n", error);
|
||||
@ -949,7 +948,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
|
||||
}
|
||||
|
||||
sprintf(buf, "quota_change%u", sdp->sd_jdesc->jd_jid);
|
||||
sdp->sd_qc_inode = gfs2_lookup_simple(pn, buf);
|
||||
sdp->sd_qc_inode = gfs2_lookup_meta(pn, buf);
|
||||
if (IS_ERR(sdp->sd_qc_inode)) {
|
||||
error = PTR_ERR(sdp->sd_qc_inode);
|
||||
fs_err(sdp, "can't find local \"qc\" file: %d\n", error);
|
||||
@ -1187,10 +1186,9 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
|
||||
/* Set up the buffer cache and fill in some fake block size values
|
||||
to allow us to read-in the on-disk superblock. */
|
||||
sdp->sd_sb.sb_bsize = sb_min_blocksize(sb, GFS2_BASIC_BLOCK);
|
||||
sdp->sd_sb.sb_bsize = sb_min_blocksize(sb, 512);
|
||||
sdp->sd_sb.sb_bsize_shift = sb->s_blocksize_bits;
|
||||
sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift -
|
||||
GFS2_BASIC_BLOCK_SHIFT;
|
||||
sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - 9;
|
||||
sdp->sd_fsb2bb = BIT(sdp->sd_fsb2bb_shift);
|
||||
|
||||
sdp->sd_tune.gt_logd_secs = sdp->sd_args.ar_commit;
|
||||
@ -1278,10 +1276,8 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
|
||||
if (!sb_rdonly(sb)) {
|
||||
error = init_threads(sdp);
|
||||
if (error) {
|
||||
gfs2_withdraw_delayed(sdp);
|
||||
if (error)
|
||||
goto fail_per_node;
|
||||
}
|
||||
}
|
||||
|
||||
error = gfs2_freeze_lock_shared(sdp);
|
||||
|
@ -470,6 +470,17 @@ static int qd_check_sync(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd,
|
||||
(sync_gen && (qd->qd_sync_gen >= *sync_gen)))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If qd_change is 0 it means a pending quota change was negated.
|
||||
* We should not sync it, but we still have a qd reference and slot
|
||||
* reference taken by gfs2_quota_change -> do_qc that need to be put.
|
||||
*/
|
||||
if (!qd->qd_change && test_and_clear_bit(QDF_CHANGE, &qd->qd_flags)) {
|
||||
slot_put(qd);
|
||||
qd_put(qd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lockref_get_not_dead(&qd->qd_lockref))
|
||||
return 0;
|
||||
|
||||
@ -912,7 +923,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
||||
{
|
||||
struct gfs2_sbd *sdp = (*qda)->qd_sbd;
|
||||
struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
|
||||
struct gfs2_alloc_parms ap = { .aflags = 0, };
|
||||
struct gfs2_alloc_parms ap = {};
|
||||
unsigned int data_blocks, ind_blocks;
|
||||
struct gfs2_holder *ghs, i_gh;
|
||||
unsigned int qx, x;
|
||||
@ -1086,8 +1097,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
||||
u32 x;
|
||||
int error;
|
||||
|
||||
if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON &&
|
||||
sdp->sd_args.ar_quota != GFS2_QUOTA_QUIET)
|
||||
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
|
||||
return 0;
|
||||
|
||||
error = gfs2_quota_hold(ip, uid, gid);
|
||||
@ -1194,17 +1204,16 @@ void gfs2_quota_unlock(struct gfs2_inode *ip)
|
||||
|
||||
#define MAX_LINE 256
|
||||
|
||||
static int print_message(struct gfs2_quota_data *qd, char *type)
|
||||
static void print_message(struct gfs2_quota_data *qd, char *type)
|
||||
{
|
||||
struct gfs2_sbd *sdp = qd->qd_sbd;
|
||||
|
||||
if (sdp->sd_args.ar_quota != GFS2_QUOTA_QUIET)
|
||||
if (sdp->sd_args.ar_quota != GFS2_QUOTA_QUIET) {
|
||||
fs_info(sdp, "quota %s for %s %u\n",
|
||||
type,
|
||||
(qd->qd_id.type == USRQUOTA) ? "user" : "group",
|
||||
from_kqid(&init_user_ns, qd->qd_id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1274,7 +1283,8 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
|
||||
* HZ)) {
|
||||
quota_send_warning(qd->qd_id,
|
||||
sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN);
|
||||
error = print_message(qd, "warning");
|
||||
print_message(qd, "warning");
|
||||
error = 0;
|
||||
qd->qd_last_warn = jiffies;
|
||||
}
|
||||
}
|
||||
@ -1288,8 +1298,7 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
|
||||
u32 x;
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
|
||||
if ((sdp->sd_args.ar_quota != GFS2_QUOTA_ON &&
|
||||
sdp->sd_args.ar_quota != GFS2_QUOTA_QUIET) ||
|
||||
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF ||
|
||||
gfs2_assert_warn(sdp, change))
|
||||
return;
|
||||
if (ip->i_diskflags & GFS2_DIF_SYSTEM)
|
||||
@ -1746,7 +1755,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
|
||||
if (gfs2_is_stuffed(ip))
|
||||
alloc_required = 1;
|
||||
if (alloc_required) {
|
||||
struct gfs2_alloc_parms ap = { .aflags = 0, };
|
||||
struct gfs2_alloc_parms ap = {};
|
||||
gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
|
||||
&data_blocks, &ind_blocks);
|
||||
blocks = 1 + data_blocks + ind_blocks;
|
||||
|
@ -15,27 +15,27 @@ struct gfs2_sbd;
|
||||
#define NO_UID_QUOTA_CHANGE INVALID_UID
|
||||
#define NO_GID_QUOTA_CHANGE INVALID_GID
|
||||
|
||||
extern int gfs2_qa_get(struct gfs2_inode *ip);
|
||||
extern void gfs2_qa_put(struct gfs2_inode *ip);
|
||||
extern int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
|
||||
extern void gfs2_quota_unhold(struct gfs2_inode *ip);
|
||||
int gfs2_qa_get(struct gfs2_inode *ip);
|
||||
void gfs2_qa_put(struct gfs2_inode *ip);
|
||||
int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
|
||||
void gfs2_quota_unhold(struct gfs2_inode *ip);
|
||||
|
||||
extern int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
|
||||
extern void gfs2_quota_unlock(struct gfs2_inode *ip);
|
||||
int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid);
|
||||
void gfs2_quota_unlock(struct gfs2_inode *ip);
|
||||
|
||||
extern int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
|
||||
struct gfs2_alloc_parms *ap);
|
||||
extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
|
||||
kuid_t uid, kgid_t gid);
|
||||
int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
|
||||
struct gfs2_alloc_parms *ap);
|
||||
void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
|
||||
kuid_t uid, kgid_t gid);
|
||||
|
||||
extern int gfs2_quota_sync(struct super_block *sb, int type);
|
||||
extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid);
|
||||
int gfs2_quota_sync(struct super_block *sb, int type);
|
||||
int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid);
|
||||
|
||||
extern int gfs2_quota_init(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
|
||||
extern int gfs2_quotad(void *data);
|
||||
int gfs2_quota_init(struct gfs2_sbd *sdp);
|
||||
void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
|
||||
int gfs2_quotad(void *data);
|
||||
|
||||
extern void gfs2_wake_up_statfs(struct gfs2_sbd *sdp);
|
||||
void gfs2_wake_up_statfs(struct gfs2_sbd *sdp);
|
||||
|
||||
static inline int gfs2_quota_lock_check(struct gfs2_inode *ip,
|
||||
struct gfs2_alloc_parms *ap)
|
||||
@ -50,8 +50,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip,
|
||||
ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON &&
|
||||
sdp->sd_args.ar_quota != GFS2_QUOTA_QUIET)
|
||||
if (sdp->sd_args.ar_quota == GFS2_QUOTA_ACCOUNT)
|
||||
return 0;
|
||||
ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid, ap);
|
||||
if (ret)
|
||||
@ -63,6 +62,7 @@ extern const struct quotactl_ops gfs2_quotactl_ops;
|
||||
int __init gfs2_qd_shrinker_init(void);
|
||||
void gfs2_qd_shrinker_exit(void);
|
||||
extern struct list_lru gfs2_qd_lru;
|
||||
extern void __init gfs2_quota_hash_init(void);
|
||||
|
||||
void __init gfs2_quota_hash_init(void);
|
||||
|
||||
#endif /* __QUOTA_DOT_H__ */
|
||||
|
@ -17,18 +17,18 @@ static inline void gfs2_replay_incr_blk(struct gfs2_jdesc *jd, u32 *blk)
|
||||
*blk = 0;
|
||||
}
|
||||
|
||||
extern int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
|
||||
int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
|
||||
struct buffer_head **bh);
|
||||
|
||||
extern int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
|
||||
extern int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
|
||||
extern void gfs2_revoke_clean(struct gfs2_jdesc *jd);
|
||||
int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
|
||||
int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
|
||||
void gfs2_revoke_clean(struct gfs2_jdesc *jd);
|
||||
|
||||
extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd, bool wait);
|
||||
extern void gfs2_recover_func(struct work_struct *work);
|
||||
extern int __get_log_header(struct gfs2_sbd *sdp,
|
||||
const struct gfs2_log_header *lh, unsigned int blkno,
|
||||
struct gfs2_log_header_host *head);
|
||||
int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd, bool wait);
|
||||
void gfs2_recover_func(struct work_struct *work);
|
||||
int __get_log_header(struct gfs2_sbd *sdp,
|
||||
const struct gfs2_log_header *lh, unsigned int blkno,
|
||||
struct gfs2_log_header_host *head);
|
||||
|
||||
#endif /* __RECOVERY_DOT_H__ */
|
||||
|
||||
|
@ -2411,13 +2411,12 @@ static void gfs2_set_alloc_start(struct gfs2_rbm *rbm,
|
||||
* @bn: Used to return the starting block number
|
||||
* @nblocks: requested number of blocks/extent length (value/result)
|
||||
* @dinode: 1 if we're allocating a dinode block, else 0
|
||||
* @generation: the generation number of the inode
|
||||
*
|
||||
* Returns: 0 or error
|
||||
*/
|
||||
|
||||
int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
|
||||
bool dinode, u64 *generation)
|
||||
bool dinode)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
struct buffer_head *dibh;
|
||||
@ -2477,10 +2476,13 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
|
||||
rbm.rgd->rd_free -= *nblocks;
|
||||
spin_unlock(&rbm.rgd->rd_rsspin);
|
||||
if (dinode) {
|
||||
u64 generation;
|
||||
|
||||
rbm.rgd->rd_dinodes++;
|
||||
*generation = rbm.rgd->rd_igeneration++;
|
||||
if (*generation == 0)
|
||||
*generation = rbm.rgd->rd_igeneration++;
|
||||
generation = rbm.rgd->rd_igeneration++;
|
||||
if (generation == 0)
|
||||
generation = rbm.rgd->rd_igeneration++;
|
||||
ip->i_generation = generation;
|
||||
}
|
||||
|
||||
gfs2_trans_add_meta(rbm.rgd->rd_gl, rbm.rgd->rd_bits[0].bi_bh);
|
||||
|
@ -22,38 +22,38 @@ struct gfs2_rgrpd;
|
||||
struct gfs2_sbd;
|
||||
struct gfs2_holder;
|
||||
|
||||
extern void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd);
|
||||
void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd);
|
||||
|
||||
extern struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk, bool exact);
|
||||
extern struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp);
|
||||
extern struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd);
|
||||
struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk, bool exact);
|
||||
struct gfs2_rgrpd *gfs2_rgrpd_get_first(struct gfs2_sbd *sdp);
|
||||
struct gfs2_rgrpd *gfs2_rgrpd_get_next(struct gfs2_rgrpd *rgd);
|
||||
|
||||
extern void gfs2_clear_rgrpd(struct gfs2_sbd *sdp);
|
||||
extern int gfs2_rindex_update(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_free_clones(struct gfs2_rgrpd *rgd);
|
||||
extern int gfs2_rgrp_go_instantiate(struct gfs2_glock *gl);
|
||||
extern void gfs2_rgrp_brelse(struct gfs2_rgrpd *rgd);
|
||||
void gfs2_clear_rgrpd(struct gfs2_sbd *sdp);
|
||||
int gfs2_rindex_update(struct gfs2_sbd *sdp);
|
||||
void gfs2_free_clones(struct gfs2_rgrpd *rgd);
|
||||
int gfs2_rgrp_go_instantiate(struct gfs2_glock *gl);
|
||||
void gfs2_rgrp_brelse(struct gfs2_rgrpd *rgd);
|
||||
|
||||
extern struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
|
||||
struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
|
||||
|
||||
#define GFS2_AF_ORLOV 1
|
||||
extern int gfs2_inplace_reserve(struct gfs2_inode *ip,
|
||||
struct gfs2_alloc_parms *ap);
|
||||
extern void gfs2_inplace_release(struct gfs2_inode *ip);
|
||||
int gfs2_inplace_reserve(struct gfs2_inode *ip,
|
||||
struct gfs2_alloc_parms *ap);
|
||||
void gfs2_inplace_release(struct gfs2_inode *ip);
|
||||
|
||||
extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
|
||||
bool dinode, u64 *generation);
|
||||
int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
|
||||
bool dinode);
|
||||
|
||||
extern void gfs2_rs_deltree(struct gfs2_blkreserv *rs);
|
||||
extern void gfs2_rs_delete(struct gfs2_inode *ip);
|
||||
extern void __gfs2_free_blocks(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
|
||||
u64 bstart, u32 blen, int meta);
|
||||
extern void gfs2_free_meta(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
|
||||
u64 bstart, u32 blen);
|
||||
extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
|
||||
extern void gfs2_unlink_di(struct inode *inode);
|
||||
extern int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr,
|
||||
unsigned int type);
|
||||
void gfs2_rs_deltree(struct gfs2_blkreserv *rs);
|
||||
void gfs2_rs_delete(struct gfs2_inode *ip);
|
||||
void __gfs2_free_blocks(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
|
||||
u64 bstart, u32 blen, int meta);
|
||||
void gfs2_free_meta(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
|
||||
u64 bstart, u32 blen);
|
||||
void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
|
||||
void gfs2_unlink_di(struct inode *inode);
|
||||
int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr,
|
||||
unsigned int type);
|
||||
|
||||
struct gfs2_rgrp_list {
|
||||
unsigned int rl_rgrps;
|
||||
@ -62,18 +62,19 @@ struct gfs2_rgrp_list {
|
||||
struct gfs2_holder *rl_ghs;
|
||||
};
|
||||
|
||||
extern void gfs2_rlist_add(struct gfs2_inode *ip, struct gfs2_rgrp_list *rlist,
|
||||
u64 block);
|
||||
extern void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist,
|
||||
unsigned int state, u16 flags);
|
||||
extern void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
|
||||
extern u64 gfs2_ri_total(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_rgrp_dump(struct seq_file *seq, struct gfs2_rgrpd *rgd,
|
||||
const char *fs_id_buf);
|
||||
extern int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
|
||||
struct buffer_head *bh,
|
||||
const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed);
|
||||
extern int gfs2_fitrim(struct file *filp, void __user *argp);
|
||||
void gfs2_rlist_add(struct gfs2_inode *ip, struct gfs2_rgrp_list *rlist,
|
||||
u64 block);
|
||||
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist,
|
||||
unsigned int state, u16 flags);
|
||||
void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
|
||||
u64 gfs2_ri_total(struct gfs2_sbd *sdp);
|
||||
void gfs2_rgrp_dump(struct seq_file *seq, struct gfs2_rgrpd *rgd,
|
||||
const char *fs_id_buf);
|
||||
int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
|
||||
struct buffer_head *bh,
|
||||
const struct gfs2_bitmap *bi, unsigned minlen,
|
||||
u64 *ptrimmed);
|
||||
int gfs2_fitrim(struct file *filp, void __user *argp);
|
||||
|
||||
/* This is how to tell if a reservation is in the rgrp tree: */
|
||||
static inline bool gfs2_rs_active(const struct gfs2_blkreserv *rs)
|
||||
@ -88,9 +89,9 @@ static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
|
||||
return first <= block && block < last;
|
||||
}
|
||||
|
||||
extern void check_and_update_goal(struct gfs2_inode *ip);
|
||||
void check_and_update_goal(struct gfs2_inode *ip);
|
||||
|
||||
extern void rgrp_lock_local(struct gfs2_rgrpd *rgd);
|
||||
extern void rgrp_unlock_local(struct gfs2_rgrpd *rgd);
|
||||
void rgrp_lock_local(struct gfs2_rgrpd *rgd);
|
||||
void rgrp_unlock_local(struct gfs2_rgrpd *rgd);
|
||||
|
||||
#endif /* __RGRP_DOT_H__ */
|
||||
|
@ -602,13 +602,15 @@ restart:
|
||||
}
|
||||
spin_unlock(&sdp->sd_jindex_spin);
|
||||
|
||||
if (!sb_rdonly(sb)) {
|
||||
if (!sb_rdonly(sb))
|
||||
gfs2_make_fs_ro(sdp);
|
||||
}
|
||||
if (gfs2_withdrawn(sdp)) {
|
||||
gfs2_destroy_threads(sdp);
|
||||
else {
|
||||
if (gfs2_withdrawn(sdp))
|
||||
gfs2_destroy_threads(sdp);
|
||||
|
||||
gfs2_quota_cleanup(sdp);
|
||||
}
|
||||
|
||||
WARN_ON(gfs2_withdrawing(sdp));
|
||||
|
||||
/* At this point, we're through modifying the disk */
|
||||
@ -1006,6 +1008,7 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
buf->f_files = sc.sc_dinodes + sc.sc_free;
|
||||
buf->f_ffree = sc.sc_free;
|
||||
buf->f_namelen = GFS2_FNAMESIZE;
|
||||
buf->f_fsid = uuid_to_fsid(sb->s_uuid.b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1299,18 +1302,8 @@ static bool gfs2_upgrade_iopen_glock(struct inode *inode)
|
||||
* As a last resort, if another node keeps holding the iopen glock
|
||||
* without showing any activity on the inode glock, we will eventually
|
||||
* time out and fail the iopen glock upgrade.
|
||||
*
|
||||
* Note that we're passing the LM_FLAG_TRY_1CB flag to the first
|
||||
* locking request as an optimization to notify lock holders as soon as
|
||||
* possible. Without that flag, they'd be notified implicitly by the
|
||||
* second locking request.
|
||||
*/
|
||||
|
||||
gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, gh);
|
||||
error = gfs2_glock_nq(gh);
|
||||
if (error != GLR_TRYFAILED)
|
||||
return !error;
|
||||
|
||||
gfs2_holder_reinit(LM_ST_EXCLUSIVE, GL_ASYNC | GL_NOCACHE, gh);
|
||||
error = gfs2_glock_nq(gh);
|
||||
if (error)
|
||||
@ -1550,7 +1543,7 @@ out:
|
||||
wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE);
|
||||
gfs2_glock_add_to_lru(ip->i_gl);
|
||||
gfs2_glock_put_eventually(ip->i_gl);
|
||||
ip->i_gl = NULL;
|
||||
rcu_assign_pointer(ip->i_gl, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1576,7 +1569,7 @@ static void gfs2_free_inode(struct inode *inode)
|
||||
kmem_cache_free(gfs2_inode_cachep, GFS2_I(inode));
|
||||
}
|
||||
|
||||
extern void free_local_statfs_inodes(struct gfs2_sbd *sdp)
|
||||
void free_local_statfs_inodes(struct gfs2_sbd *sdp)
|
||||
{
|
||||
struct local_statfs_inode *lsi, *safe;
|
||||
|
||||
@ -1591,8 +1584,8 @@ extern void free_local_statfs_inodes(struct gfs2_sbd *sdp)
|
||||
}
|
||||
}
|
||||
|
||||
extern struct inode *find_local_statfs_inode(struct gfs2_sbd *sdp,
|
||||
unsigned int index)
|
||||
struct inode *find_local_statfs_inode(struct gfs2_sbd *sdp,
|
||||
unsigned int index)
|
||||
{
|
||||
struct local_statfs_inode *lsi;
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#define GFS2_FS_FORMAT_MIN (1801)
|
||||
#define GFS2_FS_FORMAT_MAX (1802)
|
||||
|
||||
extern void gfs2_lm_unmount(struct gfs2_sbd *sdp);
|
||||
void gfs2_lm_unmount(struct gfs2_sbd *sdp);
|
||||
|
||||
static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
|
||||
{
|
||||
@ -26,33 +26,33 @@ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
|
||||
return x;
|
||||
}
|
||||
|
||||
extern void gfs2_jindex_free(struct gfs2_sbd *sdp);
|
||||
void gfs2_jindex_free(struct gfs2_sbd *sdp);
|
||||
|
||||
extern struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid);
|
||||
extern int gfs2_jdesc_check(struct gfs2_jdesc *jd);
|
||||
extern int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename,
|
||||
struct gfs2_inode **ipp);
|
||||
struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid);
|
||||
int gfs2_jdesc_check(struct gfs2_jdesc *jd);
|
||||
int gfs2_lookup_in_master_dir(struct gfs2_sbd *sdp, char *filename,
|
||||
struct gfs2_inode **ipp);
|
||||
|
||||
extern int gfs2_make_fs_rw(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_make_fs_ro(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_online_uevent(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_destroy_threads(struct gfs2_sbd *sdp);
|
||||
extern int gfs2_statfs_init(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
|
||||
s64 dinodes);
|
||||
extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc,
|
||||
const void *buf);
|
||||
extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc,
|
||||
void *buf);
|
||||
extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh);
|
||||
extern int gfs2_statfs_sync(struct super_block *sb, int type);
|
||||
extern void gfs2_freeze_func(struct work_struct *work);
|
||||
extern void gfs2_thaw_freeze_initiator(struct super_block *sb);
|
||||
int gfs2_make_fs_rw(struct gfs2_sbd *sdp);
|
||||
void gfs2_make_fs_ro(struct gfs2_sbd *sdp);
|
||||
void gfs2_online_uevent(struct gfs2_sbd *sdp);
|
||||
void gfs2_destroy_threads(struct gfs2_sbd *sdp);
|
||||
int gfs2_statfs_init(struct gfs2_sbd *sdp);
|
||||
void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
|
||||
s64 dinodes);
|
||||
void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc,
|
||||
const void *buf);
|
||||
void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc,
|
||||
void *buf);
|
||||
void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh);
|
||||
int gfs2_statfs_sync(struct super_block *sb, int type);
|
||||
void gfs2_freeze_func(struct work_struct *work);
|
||||
void gfs2_thaw_freeze_initiator(struct super_block *sb);
|
||||
|
||||
extern void free_local_statfs_inodes(struct gfs2_sbd *sdp);
|
||||
extern struct inode *find_local_statfs_inode(struct gfs2_sbd *sdp,
|
||||
unsigned int index);
|
||||
extern void free_sbd(struct gfs2_sbd *sdp);
|
||||
void free_local_statfs_inodes(struct gfs2_sbd *sdp);
|
||||
struct inode *find_local_statfs_inode(struct gfs2_sbd *sdp,
|
||||
unsigned int index);
|
||||
void free_sbd(struct gfs2_sbd *sdp);
|
||||
|
||||
extern struct file_system_type gfs2_fs_type;
|
||||
extern struct file_system_type gfs2meta_fs_type;
|
||||
|
@ -34,17 +34,17 @@ static inline unsigned int gfs2_rg_blocks(const struct gfs2_inode *ip, unsigned
|
||||
return rgd->rd_length;
|
||||
}
|
||||
|
||||
extern int __gfs2_trans_begin(struct gfs2_trans *tr, struct gfs2_sbd *sdp,
|
||||
unsigned int blocks, unsigned int revokes,
|
||||
unsigned long ip);
|
||||
extern int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
|
||||
unsigned int revokes);
|
||||
int __gfs2_trans_begin(struct gfs2_trans *tr, struct gfs2_sbd *sdp,
|
||||
unsigned int blocks, unsigned int revokes,
|
||||
unsigned long ip);
|
||||
int gfs2_trans_begin(struct gfs2_sbd *sdp, unsigned int blocks,
|
||||
unsigned int revokes);
|
||||
|
||||
extern void gfs2_trans_end(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh);
|
||||
extern void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh);
|
||||
extern void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
|
||||
extern void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len);
|
||||
extern void gfs2_trans_free(struct gfs2_sbd *sdp, struct gfs2_trans *tr);
|
||||
void gfs2_trans_end(struct gfs2_sbd *sdp);
|
||||
void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh);
|
||||
void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh);
|
||||
void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
|
||||
void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len);
|
||||
void gfs2_trans_free(struct gfs2_sbd *sdp, struct gfs2_trans *tr);
|
||||
|
||||
#endif /* __TRANS_DOT_H__ */
|
||||
|
@ -147,10 +147,10 @@ static inline void gfs2_metatype_set(struct buffer_head *bh, u16 type,
|
||||
int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function,
|
||||
char *file, unsigned int line);
|
||||
|
||||
extern int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
bool verbose);
|
||||
extern int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp);
|
||||
extern void gfs2_freeze_unlock(struct gfs2_holder *freeze_gh);
|
||||
int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
bool verbose);
|
||||
int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp);
|
||||
void gfs2_freeze_unlock(struct gfs2_holder *freeze_gh);
|
||||
|
||||
#define gfs2_io_error(sdp) \
|
||||
gfs2_io_error_i((sdp), __func__, __FILE__, __LINE__)
|
||||
|
@ -639,7 +639,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
|
||||
u64 block;
|
||||
int error;
|
||||
|
||||
error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL);
|
||||
error = gfs2_alloc_blocks(ip, &block, &n, 0);
|
||||
if (error)
|
||||
return error;
|
||||
gfs2_trans_remove_revoke(sdp, block, 1);
|
||||
@ -701,7 +701,7 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
|
||||
int mh_size = sizeof(struct gfs2_meta_header);
|
||||
unsigned int n = 1;
|
||||
|
||||
error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL);
|
||||
error = gfs2_alloc_blocks(ip, &block, &n, 0);
|
||||
if (error)
|
||||
return error;
|
||||
gfs2_trans_remove_revoke(sdp, block, 1);
|
||||
@ -1002,7 +1002,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
|
||||
} else {
|
||||
u64 blk;
|
||||
unsigned int n = 1;
|
||||
error = gfs2_alloc_blocks(ip, &blk, &n, 0, NULL);
|
||||
error = gfs2_alloc_blocks(ip, &blk, &n, 0);
|
||||
if (error)
|
||||
return error;
|
||||
gfs2_trans_remove_revoke(sdp, blk, 1);
|
||||
|
@ -50,14 +50,14 @@ struct gfs2_ea_location {
|
||||
struct gfs2_ea_header *el_prev;
|
||||
};
|
||||
|
||||
extern int __gfs2_xattr_set(struct inode *inode, const char *name,
|
||||
const void *value, size_t size,
|
||||
int flags, int type);
|
||||
extern ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size);
|
||||
extern int gfs2_ea_dealloc(struct gfs2_inode *ip);
|
||||
int __gfs2_xattr_set(struct inode *inode, const char *name,
|
||||
const void *value, size_t size,
|
||||
int flags, int type);
|
||||
ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size);
|
||||
int gfs2_ea_dealloc(struct gfs2_inode *ip);
|
||||
|
||||
/* Exported to acl.c */
|
||||
|
||||
extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data);
|
||||
int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data);
|
||||
|
||||
#endif /* __EATTR_DOT_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user