From: Jan Kara Date: Mon, 20 May 2002 02:34:14 +0000 (-0700) Subject: [PATCH] [6/13] quota-6-bytes X-Git-Tag: v2.5.17~10^2~7 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=ce9fb13943c8e4d932f152dbd08097ed36c62a54;p=history.git [PATCH] [6/13] quota-6-bytes This patch implements counting of used space in inodes in bytes. New field i_bytes is added and used space modulo 512 is kept in it (rest is still kept in i_blocks). Functions manipulating both i_blocks and i_bytes are implemented (inode_add_bytes(), inode_sub_bytes() and inode_set_bytes()). Filesystems allocating only in whole blocks can safely ignore i_bytes field and continue using i_blocks... --- diff --git a/fs/dquot.c b/fs/dquot.c index d697e4b18e16..1503708a4657 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -972,7 +972,7 @@ int dquot_alloc_space(struct inode *inode, qsize_t number, int warn) continue; dquot_incr_space(dquot[cnt], number); } - inode->i_blocks += number >> 9; + inode_add_bytes(inode, number); /* NOBLOCK End */ ret = QUOTA_OK; warn_put_all: @@ -1040,7 +1040,7 @@ void dquot_free_space(struct inode *inode, qsize_t number) dquot_decr_space(dquot, number); dqputduplicate(dquot); } - inode->i_blocks -= number >> 9; + inode_sub_bytes(inode, number); unlock_kernel(); /* NOBLOCK End */ } @@ -1103,7 +1103,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) } } /* NOBLOCK START: From now on we shouldn't block */ - space = ((qsize_t)inode->i_blocks) << 9; + space = inode_get_bytes(inode); /* Build the transfer_from list and check the limits */ for (cnt = 0; cnt < MAXQUOTAS; cnt++) { /* The second test can fail when quotaoff is in progress... */ @@ -1162,9 +1162,9 @@ warn_put_all: struct dquot_operations dquot_operations = { initialize: dquot_initialize, /* mandatory */ drop: dquot_drop, /* mandatory */ - alloc_block: dquot_alloc_space, + alloc_space: dquot_alloc_space, alloc_inode: dquot_alloc_inode, - free_block: dquot_free_space, + free_space: dquot_free_space, free_inode: dquot_free_inode, transfer: dquot_transfer }; diff --git a/fs/inode.c b/fs/inode.c index 61e3f6678737..0ceabe7b934b 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -95,6 +95,7 @@ static struct inode *alloc_inode(struct super_block *sb) atomic_set(&inode->i_writecount, 0); inode->i_size = 0; inode->i_blocks = 0; + inode->i_bytes = 0; inode->i_generation = 0; memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); inode->i_pipe = NULL; diff --git a/include/linux/fs.h b/include/linux/fs.h index 0f789728ce3a..f50388ea30dc 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -370,6 +370,7 @@ struct inode { unsigned long i_blksize; unsigned long i_blocks; unsigned long i_version; + unsigned short i_bytes; struct semaphore i_sem; struct inode_operations *i_op; struct file_operations *i_fop; /* former ->i_op->default_file_ops */ @@ -427,6 +428,39 @@ struct fown_struct { int signum; /* posix.1b rt signal to be delivered on IO */ }; +static inline void inode_add_bytes(struct inode *inode, loff_t bytes) +{ + inode->i_blocks += bytes >> 9; + bytes &= 511; + inode->i_bytes += bytes; + if (inode->i_bytes >= 512) { + inode->i_blocks++; + inode->i_bytes -= 512; + } +} + +static inline void inode_sub_bytes(struct inode *inode, loff_t bytes) +{ + inode->i_blocks -= bytes >> 9; + bytes &= 511; + if (inode->i_bytes < bytes) { + inode->i_blocks--; + inode->i_bytes += 512; + } + inode->i_bytes -= bytes; +} + +static inline loff_t inode_get_bytes(struct inode *inode) +{ + return (((loff_t)inode->i_blocks) << 9) + inode->i_bytes; +} + +static inline void inode_set_bytes(struct inode *inode, loff_t bytes) +{ + inode->i_blocks = bytes >> 9; + inode->i_bytes = bytes & 511; +} + /* * Track a single file's readahead state */ diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index ab702b2607cf..b5da5ff5bb9a 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -70,7 +70,7 @@ static __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t } } else - inode->i_blocks += nr >> 9; + inode_add_bytes(inode, nr); unlock_kernel(); return 0; } @@ -94,7 +94,7 @@ static __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) } } else - inode->i_blocks += nr >> 9; + inode_add_bytes(inode, nr); unlock_kernel(); return 0; } @@ -127,7 +127,7 @@ static __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) if (sb_any_quota_enabled(inode->i_sb)) inode->i_sb->dq_op->free_space(inode, nr); else - inode->i_blocks -= nr >> 9; + inode_sub_bytes(inode, nr); unlock_kernel(); } @@ -177,7 +177,7 @@ static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr) extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); - inode->i_blocks += nr >> 9; + inode_add_bytes(inode, nr); unlock_kernel(); return 0; } @@ -192,7 +192,7 @@ extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); - inode->i_blocks += nr >> 9; + inode_add_bytes(inode, nr); unlock_kernel(); return 0; } @@ -207,7 +207,7 @@ extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { lock_kernel(); - inode->i_blocks -= nr >> 9; + inode_sub_bytes(inode, nr); unlock_kernel(); } @@ -222,8 +222,8 @@ extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) #define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) DQUOT_PREALLOC_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) #define DQUOT_PREALLOC_BLOCK(inode, nr) DQUOT_PREALLOC_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) #define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) DQUOT_ALLOC_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) -#define DQUOT_ALLOC_BLOCK(inode, nr) DQUOT_ALLOC_SPACE(inode, fs_to_dq_blocks(nr, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) +#define DQUOT_ALLOC_BLOCK(inode, nr) DQUOT_ALLOC_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) #define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) DQUOT_FREE_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) -#define DQUOT_FREE_BLOCK(inode, nr) DQUOT_FREE_SPACE(inode, fs_to_dq_blocks(nr, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) +#define DQUOT_FREE_BLOCK(inode, nr) DQUOT_FREE_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits) #endif /* _LINUX_QUOTAOPS_ */