Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfsd: Pull write-gathering code out of nfsd_vfs_write

This is a relatively self-contained piece of code that handles a special
case--move it to its own function.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

+39 -30
+39 -30
fs/nfsd/vfs.c
··· 963 963 mutex_unlock(&dentry->d_inode->i_mutex); 964 964 } 965 965 966 + /* 967 + * Gathered writes: If another process is currently writing to the file, 968 + * there's a high chance this is another nfsd (triggered by a bulk write 969 + * from a client's biod). Rather than syncing the file with each write 970 + * request, we sleep for 10 msec. 971 + * 972 + * I don't know if this roughly approximates C. Juszak's idea of 973 + * gathered writes, but it's a nice and simple solution (IMHO), and it 974 + * seems to work:-) 975 + * 976 + * Note: we do this only in the NFSv2 case, since v3 and higher have a 977 + * better tool (separate unstable writes and commits) for solving this 978 + * problem. 979 + */ 980 + static int wait_for_concurrent_writes(struct file *file) 981 + { 982 + struct inode *inode = file->f_path.dentry->d_inode; 983 + static ino_t last_ino; 984 + static dev_t last_dev; 985 + int err = 0; 986 + 987 + if (atomic_read(&inode->i_writecount) > 1 988 + || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) { 989 + dprintk("nfsd: write defer %d\n", task_pid_nr(current)); 990 + msleep(10); 991 + dprintk("nfsd: write resume %d\n", task_pid_nr(current)); 992 + } 993 + 994 + if (inode->i_state & I_DIRTY) { 995 + dprintk("nfsd: write sync %d\n", task_pid_nr(current)); 996 + err = nfsd_sync(file); 997 + } 998 + last_ino = inode->i_ino; 999 + last_dev = inode->i_sb->s_dev; 1000 + return err; 1001 + } 1002 + 966 1003 static __be32 967 1004 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 968 1005 loff_t offset, struct kvec *vec, int vlen, ··· 1063 1026 if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) 1064 1027 kill_suid(dentry); 1065 1028 1066 - if (host_err >= 0 && stable && use_wgather) { 1067 - static ino_t last_ino; 1068 - static dev_t last_dev; 1069 - 1070 - /* 1071 - * Gathered writes: If another process is currently 1072 - * writing to the file, there's a high chance 1073 - * this is another nfsd (triggered by a bulk write 1074 - * from a client's biod). Rather than syncing the 1075 - * file with each write request, we sleep for 10 msec. 1076 - * 1077 - * I don't know if this roughly approximates 1078 - * C. Juszak's idea of gathered writes, but it's a 1079 - * nice and simple solution (IMHO), and it seems to 1080 - * work:-) 1081 - */ 1082 - if (atomic_read(&inode->i_writecount) > 1 1083 - || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) { 1084 - dprintk("nfsd: write defer %d\n", task_pid_nr(current)); 1085 - msleep(10); 1086 - dprintk("nfsd: write resume %d\n", task_pid_nr(current)); 1087 - } 1088 - 1089 - if (inode->i_state & I_DIRTY) { 1090 - dprintk("nfsd: write sync %d\n", task_pid_nr(current)); 1091 - host_err=nfsd_sync(file); 1092 - } 1093 - last_ino = inode->i_ino; 1094 - last_dev = inode->i_sb->s_dev; 1095 - } 1029 + if (host_err >= 0 && stable && use_wgather) 1030 + host_err = wait_for_concurrent_writes(file); 1096 1031 1097 1032 dprintk("nfsd: write complete host_err=%d\n", host_err); 1098 1033 if (host_err >= 0)